/// <summary>Fills up canister to the maximum capacity.</summary> /// <param name="item">Item to refill.</param> void RefillCanister(KIS_Item item) { var canisterResource = GetCanisterFuelResource(item); var needResource = canisterResource.maxAmount - canisterResource.amount; if (needResource <= double.Epsilon) { ScreenMessaging.ShowPriorityScreenMessage(NoNeedToRefillCanisterMsg); return; } double newAmount; if (_mainResourceName != StockResourceNames.EvaPropellant) { var hasAmount = item.inventory.part.RequestResource(_mainResourceName, needResource); if (hasAmount <= double.Epsilon) { ScreenMessaging.ShowPriorityScreenMessage( NoResourceInVesselMsg.Format(canisterResource.resourceName)); UISounds.PlayBipWrong(); return; } newAmount = canisterResource.amount + hasAmount; ScreenMessaging.ShowPriorityScreenMessage( CanisterPartialRefilledMsg.Format(canisterResource.resourceName, hasAmount)); } else { newAmount = canisterResource.maxAmount; ScreenMessaging.ShowPriorityScreenMessage(CanisterFullyRefilledMsg); } item.UpdateResource(_mainResourceName, newAmount); UISoundPlayer.instance.Play(refuelSndPath); }
/// <summary>Handles keyboard input.</summary> private void UpdateKey() { if (isRunning) { if (Input.GetKeyDown(KeyCode.Escape) || Input.GetKeyDown(KeyCode.Return)) { Logger.logInfo("Cancel key pressed, stop eva attach mode"); StopPointer(); SendPointerClick(PointerTarget.Nothing, Vector3.zero, Quaternion.identity, null, null); } if (GameSettings.Editor_toggleSymMethod.GetKeyDown()) // "R" by default. { if (pointerTarget != PointerTarget.PartMount && attachNodes.Count() > 1) { attachNodeIndex++; if (attachNodeIndex > (attachNodes.Count - 1)) { attachNodeIndex = 0; } Logger.logInfo("Attach node index changed to: {0}", attachNodeIndex); UpdatePointerAttachNode(); ResetMouseOver(); SendPointerState(pointerTarget, PointerState.OnChangeAttachNode, null, null); } else { ScreenMessaging.ShowInfoScreenMessage("This part has only one attach node!"); audioBipWrong.Play(); } } } }
/// <summary> /// Refuels kerbal's EVA pack up to the maximum, and decreases canister reserve. /// </summary> /// <param name="item">Item to get fuel from.</param> protected virtual void RefillEVAPack(KIS_Item item) { var canisterFuelResource = GetCanisterFuelResource(item); var evaFuelResource = item.inventory.part.Resources.Get( item.inventory.part.GetComponent <KerbalEVA>().propellantResourceName); var needsFuel = evaFuelResource.maxAmount - evaFuelResource.amount; if (needsFuel < double.Epsilon) { ScreenMessaging.ShowPriorityScreenMessage(NoNeedToRefillMsg); } else { if (canisterFuelResource.amount < double.Epsilon) { ScreenMessaging.ShowPriorityScreenMessage(CanisterIsEmptyMsg); UISounds.PlayBipWrong(); } else { var canRefuel = Math.Min(needsFuel, canisterFuelResource.amount); item.UpdateResource(StockResourceNames.EvaPropellant, canisterFuelResource.amount - canRefuel); evaFuelResource.amount += canRefuel; if (canRefuel < needsFuel) { ScreenMessaging.ShowPriorityScreenMessage(NotEnoughPropellantMsg); } else { ScreenMessaging.ShowPriorityScreenMessage(JetpackRefueledMsg); } UISoundPlayer.instance.Play(refuelSndPath); } } }
public override void OnItemUse(KIS_Item item, KIS_Item.UseFrom useFrom) { string shipProp = this.settings.ShipPropellantName; string evaProp = this.settings.EvaPropellantName; if (useFrom != KIS_Item.UseFrom.KeyUp && item.inventory.invType == ModuleKISInventory.InventoryType.Pod) { double fuelLeft = 0; double fuelMax = 0; fuelLeft = GetCanisterFuelResource(item).amount; fuelMax = GetCanisterFuelResource(item).maxAmount; double fuelRequest = item.inventory.part.RequestResource(shipProp, fuelMax - fuelLeft); item.SetResource(evaProp, fuelLeft + fuelRequest); if (fuelRequest < fuelMax - fuelLeft) { ScreenMessaging.ShowPriorityScreenMessage("Warning! Only " + Math.Round(fuelRequest, 2).ToString() + " units of " + shipProp + " were left to fill the tank!"); } else { ScreenMessaging.ShowPriorityScreenMessage("Fuel tank refueled with " + Math.Round(fuelRequest, 2).ToString() + " units of " + shipProp + "."); } UISoundPlayer.instance.Play(refuelSndPath); } else { base.OnItemUse(item, useFrom); } }
/// <summary>Handles keyboard input.</summary> private void UpdateKey() { if (isRunning) { if (KIS_Shared.IsKeyUp(KeyCode.Escape) || KIS_Shared.IsKeyDown(KeyCode.Return)) { Debug.Log("Cancel key pressed, stop eva attach mode"); StopPointer(unlockUI: false); SendPointerClick(PointerTarget.Nothing, Vector3.zero, Quaternion.identity, null, null); // Delay unlocking to not let ESC be handled by the game. AsyncCall.CallOnEndOfFrame(this, UnlockUI); } if (GameSettings.Editor_toggleSymMethod.GetKeyDown()) // "R" by default. { if (pointerTarget != PointerTarget.PartMount && attachNodes.Count() > 1) { attachNodeIndex++; if (attachNodeIndex > (attachNodes.Count - 1)) { attachNodeIndex = 0; } Debug.LogFormat("Attach node index changed to: {0}", attachNodeIndex); UpdatePointerAttachNode(); ResetMouseOver(); SendPointerState(pointerTarget, PointerState.OnChangeAttachNode, null, null); } else { ScreenMessaging.ShowInfoScreenMessage("This part has only one attach node!"); audioBipWrong.Play(); } } } }
/// <summary>Handles keyboard input.</summary> private void UpdateKey() { if (isRunning) { if (KIS_Shared.IsKeyUp(KeyCode.Escape) || KIS_Shared.IsKeyDown(KeyCode.Return)) { DebugEx.Fine("Cancel key pressed, stop eva attach mode"); CancelPointer(this); } if (GameSettings.Editor_toggleSymMethod.GetKeyDown()) // "R" by default. { if (pointerTarget != PointerTarget.PartMount && attachNodes.Count() > 1) { if (attachNodeIndex < attachNodes.Count - 1) { attachNodeIndex++; } else { attachNodeIndex = 0; } DebugEx.Fine("Attach node index changed to: {0}", attachNodeIndex); ResetMouseOver(); SendPointerState(pointerTarget, PointerState.OnChangeAttachNode, null, null); } else { ScreenMessaging.ShowInfoScreenMessage(OnlyOneAttachNodeMsg); UISounds.PlayBipWrong(); } } } }
/// <summary> /// Refuels kerbal's EVA pack up to the maximum, and decreases canister reserve. /// </summary> /// <param name="item">Item to get fuel from.</param> void RefillEvaPack(KIS_Item item) { var evaFuelResource = item.inventory.part.Resources.Get(StockResourceNames.EvaPropellant); var needsFuel = evaFuelResource.maxAmount - evaFuelResource.amount; if (needsFuel < double.Epsilon) { ScreenMessaging.ShowPriorityScreenMessage(NoNeedToRefillJetpackMsg); return; } var canisterFuelResource = GetCanisterFuelResource(item); if (canisterFuelResource.amount < double.Epsilon) { ScreenMessaging.ShowPriorityScreenMessage(CanisterIsEmptyMsg); UISounds.PlayBipWrong(); return; } var canRefuel = Math.Min(needsFuel, canisterFuelResource.amount); item.UpdateResource(_mainResourceName, -canRefuel, isAmountRelative: true); evaFuelResource.amount += canRefuel; if (canRefuel < needsFuel) { ScreenMessaging.ShowPriorityScreenMessage(JetpackPartiallyRefueledMsg.Format(canRefuel)); } else { ScreenMessaging.ShowPriorityScreenMessage(JetpackFullyRefueledMsg); } UISoundPlayer.instance.Play(refuelSndPath); }
/// <summary>Displays linking status in real time.</summary> void UpdateLinkingState() { // Catch the hovered part, a possible target on it, and the link feasibility. if (Mouse.HoveredPart != lastHoveredPart) { lastHoveredPart = Mouse.HoveredPart; targetCandidateIsGood = false; if (lastHoveredPart == null) { targetCandidate = null; } else { targetCandidate = lastHoveredPart.Modules.OfType <ILinkTarget>() .FirstOrDefault(x => x.cfgLinkType == cfgLinkType && x.linkState == LinkState.AcceptingLinks); if (targetCandidate != null) { var linkStatusErrors = new List <string>() .Concat(CheckBasicLinkConditions(targetCandidate, checkStates: true)) .Concat(linkRenderer.CheckColliderHits(nodeTransform, targetCandidate.nodeTransform)) .Concat(linkJoint.CheckConstraints(this, targetCandidate)) .ToArray(); if (linkStatusErrors.Length == 0) { targetCandidateIsGood = true; statusScreenMessage.message = CanBeConnectedMsg.Format( Vector3.Distance(nodeTransform.position, targetCandidate.nodeTransform.position)); } else { statusScreenMessage.message = ScreenMessaging.SetColorToRichText( String.Join("\n", linkStatusErrors), ScreenMessaging.ErrorColor); } } } // Show the possible link or indicate the error. if (targetCandidate != null) { linkRenderer.colorOverride = targetCandidateIsGood ? GoodLinkColor : BadLinkColor; linkRenderer.StartRenderer(nodeTransform, targetCandidate.nodeTransform); } else { linkRenderer.colorOverride = BadLinkColor; linkRenderer.StopRenderer(); } } // Update linking messages (it needs to be refreshed to not go out by timeout). if (targetCandidate == null) { statusScreenMessage.message = LinkingInProgressMsg; } ScreenMessages.PostScreenMessage(statusScreenMessage); }
public void ActivateEvent() { if (!activated) { activated = true; sndTimeStart.Play(); sndTimeLoop.Play(); PartModuleUtils.SetupEvent(this, ActivateEvent, x => x.active = false); PartModuleUtils.SetupEvent(this, SetupEvent, x => x.active = false); ScreenMessaging.ShowPriorityScreenMessage(TimeToEscapeMsg.Format((int)delay)); } }
/// <summary> /// Iterates through <see cref="CameraStabilization"/> values and pick next mode on each call. /// </summary> void SelectNextStabilizationMode() { if (_cameraStabilizationMode == CameraStabilization.None) { _cameraStabilizationMode = CameraStabilization.KeepPosition; } else if (_cameraStabilizationMode == CameraStabilization.KeepPosition) { _cameraStabilizationMode = CameraStabilization.KeepDistanceAndRotation; } else { _cameraStabilizationMode = CameraStabilization.None; } ScreenMessaging.ShowPriorityScreenMessage( CameraStabilizationModeChangedMsg.Format(CameraStabilizationModeLookup.Lookup(_cameraStabilizationMode))); }
public bool StackAdd(float qty, bool checkVolume = true) { if (qty <= 0) { return(false); } float newVolume = inventory.totalVolume + (volume * qty); if (checkVolume && newVolume > inventory.maxVolume) { ScreenMessaging.ShowPriorityScreenMessage("Max destination volume reached (+{0:#.####})", newVolume - inventory.maxVolume); return(false); } quantity += qty; inventory.RefreshMassAndVolume(); return(true); }
/// <summary>Shows a UI messages with regard to the currently active vessel.</summary> /// <remarks> /// The UI messages from the active vessel are shown at the highest priority to bring attention /// of the player. The messages from the inactive vessels are shown only as a status, that is not /// intended to distract the player from the current vessel operations. /// </remarks> /// <param name="msg">The message to show.</param> /// <param name="isError"> /// Tells if the messages is an error condition report. Such messages will be highlighted. /// </param> protected void ShowStatusMessage(string msg, bool isError = false) { if (FlightGlobals.ActiveVessel != vessel) { msg = $"[{vessel.vesselName}]: {msg}"; } if (isError) { msg = ScreenMessaging.SetColorToRichText(msg, ScreenMessaging.ErrorColor); } var duration = isError ? ScreenMessaging.DefaultErrorTimeout : ScreenMessaging.DefaultMessageTimeout; var location = FlightGlobals.ActiveVessel == vessel ? ScreenMessageStyle.UPPER_CENTER : (isError ? ScreenMessageStyle.UPPER_RIGHT : ScreenMessageStyle.UPPER_LEFT); ScreenMessages.PostScreenMessage(msg, duration, location); }
public override void OnItemUse(KIS_Item item, KIS_Item.UseFrom useFrom) { if (ModEnabled && KISIntegrationEnabled) { if (useFrom != KIS_Item.UseFrom.KeyUp && item.inventory.invType == ModuleKISInventory.InventoryType.Pod) { double fuelLeft = 0; double fuelMax = 0; fuelLeft = ModuleKISItemEvaPropellant.GetCanisterFuelResource(item).amount; fuelMax = ModuleKISItemEvaPropellant.GetCanisterFuelResource(item).maxAmount; double takenFuel = item.inventory.part.RequestResource(shipPropName, (fuelMax - fuelLeft) / fuelConvFactor); double fuelRequest = takenFuel * fuelConvFactor; item.UpdateResource(resourceName, fuelLeft + fuelRequest); if (fuelRequest + 0.001 < fuelMax - fuelLeft) //0.001 for floating point rounding issues. Don't want to trigger insufficient fuel all the time. { if (ShowLowFuelWarning) { PopupDialog.SpawnPopupDialog(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), "OnItemUse", "Low EVA Fuel!", "Warning! Only " + Math.Round(takenFuel, 2).ToString() + " units of " + shipPropName + " were available to refill the EVA Canister! Meaning it only has " + Math.Round(fuelLeft + fuelRequest, 2).ToString() + " units of " + resourceName + "!", "OK", false, HighLogic.UISkin); } } else { if (ShowInfoMessage) { ScreenMessaging.ShowPriorityScreenMessage("Fuel tank refueled with " + Math.Round(takenFuel, 2).ToString() + " units of " + shipPropName + "."); } } UISoundPlayer.instance.Play(refuelSndPath); } else { base.OnItemUse(item, useFrom); } } else { base.OnItemUse(item, useFrom); } }
public bool CanStackAdd(float qty, bool checkVolume = true) { if (qty <= 0) { return(false); } if (equipped) { ScreenMessaging.ShowPriorityScreenMessage("Cannot stack with equipped item"); UISounds.PlayBipWrong(); return(false); } float newVolume = inventory.totalVolume + (volume * qty); if (checkVolume && newVolume > inventory.maxVolume) { ScreenMessaging.ShowPriorityScreenMessage("Max destination volume reached (+{0:#.####})", newVolume - inventory.maxVolume); return(false); } return(true); }
public bool CanStackAdd(float qty, bool checkVolume = true) { if (qty <= 0) { return(false); } if (equipped) { ScreenMessaging.ShowPriorityScreenMessage(CannotStackItemEquippedMsg); UISounds.PlayBipWrong(); return(false); } float newVolume = inventory.totalVolume + (volume * qty); if (checkVolume && newVolume > inventory.maxVolume) { ScreenMessaging.ShowPriorityScreenMessage( CannotStackMaxVolumeReachedMsg.Format(newVolume - inventory.maxVolume)); return(false); } return(true); }
public static bool createFXSound(Part part, FXGroup group, string sndPath, bool loop, float maxDistance = 30f) { group.audio = part.gameObject.AddComponent <AudioSource>(); group.audio.volume = GameSettings.SHIP_VOLUME; group.audio.rolloffMode = AudioRolloffMode.Linear; group.audio.dopplerLevel = 0f; group.audio.spatialBlend = 1f; group.audio.maxDistance = maxDistance; group.audio.loop = loop; group.audio.playOnAwake = false; if (GameDatabase.Instance.ExistsAudioClip(sndPath)) { group.audio.clip = GameDatabase.Instance.GetAudioClip(sndPath); return(true); } else { Logger.logError("Sound not found in the game database !"); ScreenMessaging.ShowPriorityScreenMessageWithTimeout( 10, "Sound file : {0} has not been found, please check your KIS installation !", sndPath); return(false); } }
public void UpdatePointer() { // Stop pointer on map if (running && MapView.MapIsEnabled) { StopPointer(); return; } // Remove pointer if not running. if (!running) { DestroyPointer(); return; } // Hide pointer if the raycast do not hit anything. if (pointerTarget == PointerTarget.Nothing) { SetPointerVisible(false); return; } SetPointerVisible(true); // Custom rotation float rotDegree = 15; if (Input.GetKey(KeyCode.LeftShift)) { rotDegree = 1; } if (GameSettings.Editor_rollLeft.GetKeyDown()) { customRot -= new Vector3(0, -1, 0) * rotDegree; } if (GameSettings.Editor_rollRight.GetKeyDown()) { customRot += new Vector3(0, -1, 0) * rotDegree; } if (GameSettings.Editor_pitchDown.GetKeyDown()) { customRot -= new Vector3(1, 0, 0) * rotDegree; } if (GameSettings.Editor_pitchUp.GetKeyDown()) { customRot += new Vector3(1, 0, 0) * rotDegree; } if (GameSettings.Editor_yawLeft.GetKeyDown()) { customRot -= new Vector3(0, 0, 1) * rotDegree; } if (GameSettings.Editor_yawRight.GetKeyDown()) { customRot += new Vector3(0, 0, 1) * rotDegree; } if (GameSettings.Editor_resetRotation.GetKeyDown()) { customRot = new Vector3(0, 0, 0); } Quaternion rotAdjust = Quaternion.Euler(0, 0, customRot.z) * Quaternion.Euler(customRot.x, customRot.y, 0); // Move to position if (pointerTarget == PointerTarget.PartMount) { //Mount snap KIS_Shared.MoveAlign(pointer.transform, pointerNodeTransform, hoveredNode.nodeTransform); } else if (pointerTarget == PointerTarget.PartNode) { //Part node snap KIS_Shared.MoveAlign(pointer.transform, pointerNodeTransform, hoveredNode.nodeTransform, rotAdjust); } else { KIS_Shared.MoveAlign(pointer.transform, pointerNodeTransform, hit, rotAdjust); } // Move above if (allowOffset) { if (pointerTarget != PointerTarget.PartMount) { if (KIS_Shared.IsKeyDown(offsetUpKey) && aboveDistance < maxOffsetDist) { aboveDistance += aboveOffsetStep; } if (KIS_Shared.IsKeyDown(offsetDownKey) && aboveDistance > -maxOffsetDist) { aboveDistance -= aboveOffsetStep; } if (GameSettings.Editor_resetRotation.GetKeyDown()) { aboveDistance = 0; } pointer.transform.position = pointer.transform.position + (hit.normal.normalized * aboveDistance); } } //Check distance float sourceDist = 0; if (sourceTransform) { sourceDist = Vector3.Distance(FlightGlobals.ActiveVessel.transform.position, sourceTransform.position); } float targetDist = Vector3.Distance(FlightGlobals.ActiveVessel.transform.position, hit.point); //Set color Color color = colorOk; bool invalidTarget = false; bool notAllowedOnMount = false; bool cannotSurfaceAttach = false; bool invalidCurrentNode = false; bool itselfIsInvalid = !allowPartItself && partToAttach != null && partToAttach.hasIndirectChild(hoveredPart); bool restrictedPart = allowedAttachmentParts != null && !allowedAttachmentParts.Contains(hoveredPart); switch (pointerTarget) { case PointerTarget.Static: case PointerTarget.StaticRb: invalidTarget = !allowStatic; break; case PointerTarget.KerbalEva: invalidTarget = !allowEva; break; case PointerTarget.Part: if (allowPart) { if (useAttachRules) { if (hoveredPart.attachRules.allowSrfAttach) { invalidCurrentNode = currentAttachNode.nodeType != AttachNode.NodeType.Surface; } else { cannotSurfaceAttach = true; } } } else { invalidTarget = true; } break; case PointerTarget.PartMount: if (allowMount) { ModuleKISPartMount pMount = hoveredPart.GetComponent <ModuleKISPartMount>(); var allowedPartNames = new List <string>(); pMount.GetMounts().TryGetValue(hoveredNode, out allowedPartNames); notAllowedOnMount = partToAttach != null && !allowedPartNames.Contains(partToAttach.partInfo.name); color = colorMountOk; } break; case PointerTarget.PartNode: invalidTarget = !allowStack; color = colorStack; break; } // Handle generic "not OK" color. if (sourceDist > maxDist || targetDist > maxDist) { color = colorDistNok; } else if (invalidTarget || cannotSurfaceAttach || invalidCurrentNode || itselfIsInvalid || restrictedPart) { color = colorNok; } color.a = 0.5f; foreach (var mr in allModelRenderers) { mr.material.color = color; } //On click. if (Input.GetMouseButtonDown(0)) { if (invalidTarget) { ScreenMessaging.ShowInfoScreenMessage(TargetObjectNotAllowedMsg); UISounds.PlayBipWrong(); } else if (itselfIsInvalid) { ScreenMessaging.ShowInfoScreenMessage(CannotAttachOnItselfMsg); UISounds.PlayBipWrong(); } else if (notAllowedOnMount) { ScreenMessaging.ShowInfoScreenMessage(NotAllowedOnTheMountMsg); UISounds.PlayBipWrong(); } else if (cannotSurfaceAttach) { ScreenMessaging.ShowInfoScreenMessage(TargetDoesntAllowSurfaceAttachMsg); UISounds.PlayBipWrong(); } else if (invalidCurrentNode) { ScreenMessaging.ShowInfoScreenMessage(NodeNotForSurfaceAttachMsg); UISounds.PlayBipWrong(); } else if (sourceDist > maxDist) { ScreenMessaging.ShowInfoScreenMessage(TooFarFromSourceMsg.Format(sourceDist, maxDist)); UISounds.PlayBipWrong(); } else if (targetDist > maxDist) { ScreenMessaging.ShowInfoScreenMessage(TooFarFromTargetMsg.Format(targetDist, maxDist)); UISounds.PlayBipWrong(); } else if (restrictedPart) { ScreenMessaging.ShowInfoScreenMessage( CannotAttachToPartMsg.Format(hoveredPart.partInfo.title)); UISounds.PlayBipWrong(); } else { SendPointerClick(pointerTarget, pointer.transform.position, pointer.transform.rotation, hoveredPart, currentAttachNode.id, hoveredNode); } } }
public void Equip() { // Only equip EVA kerbals. if (!prefabModule || !inventory.vessel.isEVA) { return; } Logger.logInfo("Equip item {0}", this.availablePart.name); //Check skill if needed if (!String.IsNullOrEmpty(prefabModule.equipSkill)) { bool skillFound = false; List <ProtoCrewMember> protoCrewMembers = inventory.vessel.GetVesselCrew(); foreach (var expEffect in protoCrewMembers[0].experienceTrait.Effects) { if (expEffect.ToString().Replace("Experience.Effects.", "") == prefabModule.equipSkill) { skillFound = true; break; } } if (!skillFound) { ScreenMessaging.ShowPriorityScreenMessage( "This item can only be used by a kerbal with the skill : {0}", prefabModule.equipSkill); PlaySound(KIS_Shared.bipWrongSndPath); return; } } // Check if already carried if (equipSlot != null) { KIS_Item equippedItem = inventory.GetEquipedItem(equipSlot); if (equippedItem != null) { if (equippedItem.carriable) { ScreenMessaging.ShowPriorityScreenMessage( "Cannot equip item, slot <{0}> already used for carrying {1}", equipSlot, equippedItem.availablePart.title); PlaySound(KIS_Shared.bipWrongSndPath); return; } equippedItem.Unequip(); } } if (equipMode == EquipMode.Model) { GameObject modelGo = availablePart.partPrefab.FindModelTransform("model").gameObject; equippedGameObj = UnityEngine.Object.Instantiate(modelGo); foreach (Collider col in equippedGameObj.GetComponentsInChildren <Collider>()) { UnityEngine.Object.DestroyImmediate(col); } evaTransform = null; var skmrs = new List <SkinnedMeshRenderer>( inventory.part.GetComponentsInChildren <SkinnedMeshRenderer>()); foreach (SkinnedMeshRenderer skmr in skmrs) { if (skmr.name != prefabModule.equipMeshName) { continue; } foreach (Transform bone in skmr.bones) { if (bone.name == prefabModule.equipBoneName) { evaTransform = bone.transform; break; } } } if (!evaTransform) { Logger.logError("evaTransform not found ! "); UnityEngine.Object.Destroy(equippedGameObj); return; } } if (equipMode == EquipMode.Part || equipMode == EquipMode.Physic) { evaTransform = null; var skmrs = new List <SkinnedMeshRenderer>( inventory.part.GetComponentsInChildren <SkinnedMeshRenderer>()); foreach (SkinnedMeshRenderer skmr in skmrs) { if (skmr.name != prefabModule.equipMeshName) { continue; } foreach (Transform bone in skmr.bones) { if (bone.name == prefabModule.equipBoneName) { evaTransform = bone.transform; break; } } } if (!evaTransform) { Logger.logError("evaTransform not found ! "); return; } Part alreadyEquippedPart = this.inventory.part.vessel.Parts.Find(p => p.partInfo.name == this.availablePart.name); if (alreadyEquippedPart) { Logger.logInfo("Part: {0} already found on eva", availablePart.name); equippedPart = alreadyEquippedPart; OnEquippedPartCoupled(equippedPart); } else { Vector3 equipPos = evaTransform.TransformPoint(prefabModule.equipPos); Quaternion equipRot = evaTransform.rotation * Quaternion.Euler(prefabModule.equipDir); equippedPart = KIS_Shared.CreatePart( partNode, equipPos, equipRot, this.inventory.part, this.inventory.part, null, null, OnEquippedPartCoupled); } if (equipMode == EquipMode.Part) { equippedGameObj = equippedPart.gameObject; } } if (prefabModule.equipRemoveHelmet) { inventory.SetHelmet(false); } PlaySound(prefabModule.moveSndPath); equipped = true; prefabModule.OnEquip(this); }
public override void OnItemUse(KIS_Item item, KIS_Item.UseFrom useFrom) { if (useFrom != KIS_Item.UseFrom.KeyUp) { if (item.inventory.invType == ModuleKISInventory.InventoryType.Pod) { // Refuel item ScreenMessaging.ShowPriorityScreenMessage("Fuel tank refueled"); foreach (KIS_Item.ResourceInfo itemRessource in item.GetResources()) { if (itemRessource.resourceName == EvaPropellantResource) { item.SetResource(EvaPropellantResource, itemRessource.maxAmount); item.inventory.PlaySound(refuelSndPath, false, false); } } } if (item.inventory.invType == ModuleKISInventory.InventoryType.Eva) { // Refuel eva foreach (KIS_Item.ResourceInfo itemRessource in item.GetResources()) { if (itemRessource.resourceName == EvaPropellantResource) { PartResource evaRessource = item.inventory.part.GetComponent <PartResource>(); if (evaRessource) { double amountToFill = evaRessource.maxAmount - evaRessource.amount; if (itemRessource.amount > amountToFill) { ScreenMessaging.ShowPriorityScreenMessage("EVA pack refueled"); evaRessource.amount = evaRessource.maxAmount; item.SetResource(EvaPropellantResource, (itemRessource.amount - amountToFill)); if (item.equippedPart) { PartResource equippedTankRessource = item.equippedPart.Resources.list.Find( p => p.resourceName == EvaPropellantResource); if (equippedTankRessource) { equippedTankRessource.amount = (itemRessource.amount - amountToFill); } } item.inventory.PlaySound(refuelSndPath, false, false); } else { if (itemRessource.amount == 0) { ScreenMessaging.ShowPriorityScreenMessage( "Fuel tank is empty ! Cannot refuel EVA pack"); } else { ScreenMessaging.ShowPriorityScreenMessage( "Available propellant is not enough to refuel, EVA pack partially refueled"); } evaRessource.amount += itemRessource.amount; item.SetResource("EVA Propellant", 0); item.inventory.PlaySound(refuelSndPath, false, false); } } } } } } }
/// <summary> /// Refuels kerbal's EVA pack up to the maximum, and decreases canister reserve. /// </summary> /// <param name="item">Item to get fuel from.</param> void RefillEvaPack(KIS_Item item) { var p = item.inventory.part; if (!p.isVesselEVA) { HostedDebugLog.Error(this, "Cannot refill non-EVA kerbal"); return; } var stockInventory = p.FindModuleImplementing <ModuleInventoryPart>(); if (stockInventory == null) { HostedDebugLog.Error(this, "Cannot find stock inventory module"); return; } var evaModule = p.FindModuleImplementing <KerbalEVA>(); var propellantResourceField = evaModule.GetType() .GetField("propellantResource", BindingFlags.Instance | BindingFlags.NonPublic); if (propellantResourceField == null) { HostedDebugLog.Error(this, "Cannot access internal KerbalEVA logic: propellant field"); return; } var propellantResource = propellantResourceField.GetValue(evaModule) as PartResource; if (propellantResource == null) { HostedDebugLog.Error(this, "Cannot access internal KerbalEVA logic: propellant field value"); return; } var needAmount = propellantResource.maxAmount - propellantResource.amount; if (needAmount <= double.Epsilon) { ScreenMessaging.ShowPriorityScreenMessage(NoNeedToRefillJetpackMsg); return; } var canisterFuelResource = GetCanisterFuelResource(item); if (canisterFuelResource.amount < double.Epsilon) { ScreenMessaging.ShowPriorityScreenMessage(CanisterIsEmptyMsg); UISounds.PlayBipWrong(); return; } var canProvide = Math.Min(needAmount, canisterFuelResource.amount); var storedResources = stockInventory.storedParts.Values.SelectMany(x => x.snapshot.resources) .Where(x => x.resourceName == StockResourceNames.EvaPropellant) .ToArray(); if (storedResources.Length == 0) { UISounds.PlayBipWrong(); DebugEx.Error("Unexpectedly no EVA resource parts found in: {0}", evaModule); return; } item.UpdateResource(_mainResourceName, -canProvide, isAmountRelative: true); p.TransferResource(propellantResource, canProvide, p); var distributeAmount = canProvide; for (var i = 0; i < storedResources.Length && canProvide > double.Epsilon; i++) { var resource = storedResources[i]; var canAccept = resource.maxAmount - resource.amount; if (canAccept <= double.Epsilon) { continue; } var refillAmount = Math.Min(canAccept, distributeAmount); resource.amount += refillAmount; resource.UpdateConfigNodeAmounts(); distributeAmount -= refillAmount; } if (canProvide < needAmount) { ScreenMessaging.ShowPriorityScreenMessage(JetpackPartiallyRefueledMsg.Format(canProvide)); } else { ScreenMessaging.ShowPriorityScreenMessage(JetpackFullyRefueledMsg); } UISoundPlayer.instance.Play(refuelSndPath); }
/// <summary>Fills up canister to the maximum capacity.</summary> /// <param name="item">Item to refill.</param> protected virtual void RefillCanister(KIS_Item item) { item.UpdateResource(StockResourceNames.EvaPropellant, GetCanisterFuelResource(item).maxAmount); ScreenMessaging.ShowPriorityScreenMessage(CanisterRefilledMsg); UISoundPlayer.instance.Play(refuelSndPath); }
public void Equip(ActorType actorType = ActorType.API) { // Only equip EVA kerbals. if (!prefabModule || inventory.invType != ModuleKISInventory.InventoryType.Eva) { DebugEx.Warning("Cannot equip item from inventory type: {0}", inventory.invType); return; } if (quantity > 1) { ScreenMessaging.ShowPriorityScreenMessage(CannotEquipItemStackedMsg); UISounds.PlayBipWrong(); return; } DebugEx.Info("Equip item: partName={0}, mode={1}", availablePart.title, equipMode); // Check if the skill is needed. Skip the check in the sandbox modes. if (HighLogic.CurrentGame.Mode != Game.Modes.SANDBOX && HighLogic.CurrentGame.Mode != Game.Modes.SCIENCE_SANDBOX && !String.IsNullOrEmpty(prefabModule.equipSkill)) { bool skillFound = false; List <ProtoCrewMember> protoCrewMembers = inventory.vessel.GetVesselCrew(); foreach (var expEffect in protoCrewMembers[0].experienceTrait.Effects) { if (expEffect.ToString().Replace("Experience.Effects.", "") == prefabModule.equipSkill) { skillFound = true; break; } } if (!skillFound) { if (actorType == ActorType.Player) { ScreenMessaging.ShowPriorityScreenMessage( CannotEquipRestrictedToSkillMsg.Format(prefabModule.equipSkill)); UISounds.PlayBipWrong(); } return; } } // Check if slot is already occupied. if (equipSlot != null) { KIS_Item equippedItem = inventory.GetEquipedItem(equipSlot); if (equippedItem != null && equippedItem != this) { if (equippedItem.carriable && actorType == ActorType.Player) { ScreenMessaging.ShowPriorityScreenMessage( CannotEquipAlreadyCarryingMsg.Format(equipSlot, equippedItem.availablePart.title)); UISounds.PlayBipWrong(); return; } equippedItem.Unequip(); } } // Find the bone for this item to follow. evaTransform = KISAddonConfig.FindEquipBone(inventory.part.transform, prefabModule.equipBoneName); if (evaTransform == null) { return; // Cannot equip! } if (equipMode == EquipMode.Model) { var modelGo = availablePart.partPrefab.FindModelTransform("model").gameObject; equippedGameObj = UnityEngine.Object.Instantiate(modelGo); equippedGameObj.transform.parent = inventory.part.transform; foreach (Collider col in equippedGameObj.GetComponentsInChildren <Collider>()) { UnityEngine.Object.DestroyImmediate(col); } } else { var alreadyEquippedPart = inventory.part.FindChildPart(availablePart.name); if (alreadyEquippedPart) { DebugEx.Info("Part {0} already found on eva, use it as the item", availablePart.name); equippedPart = alreadyEquippedPart; // This magic is copied from the KervalEVA.OnVesselGoOffRails() method. // There must be at least 3 fixed frames delay before updating the colliders. AsyncCall.WaitForPhysics( equippedPart, 3, () => false, failure: () => OnEquippedPartReady(equippedPart)); if (equipMode == EquipMode.Part) { // Ensure the part doesn't have rigidbody and is not affected by physics. // The part may not like it. equippedPart.PhysicsSignificance = 1; // Disable physics on the part. UnityEngine.Object.Destroy(equippedPart.rb); } } else { Vector3 equipPos = evaTransform.TransformPoint(prefabModule.equipPos); Quaternion equipRot = evaTransform.rotation * Quaternion.Euler(prefabModule.equipDir); equippedPart = KIS_Shared.CreatePart( partNode, equipPos, equipRot, inventory.part, coupleToPart: inventory.part, srcAttachNodeId: "srfAttach", onPartReady: OnEquippedPartReady, createPhysicsless: equipMode != EquipMode.Physic); } if (equipMode == EquipMode.Part) { equippedGameObj = equippedPart.gameObject; } } // Hide the stock meshes if the custom helmet is equipped. if (equipSlot == HelmetSlotName) { var kerbalModule = inventory.part.FindModuleImplementing <KerbalEVA>(); if (kerbalModule.helmetTransform != null) { for (var i = 0; i < kerbalModule.helmetTransform.childCount; i++) { kerbalModule.helmetTransform.GetChild(i).gameObject.SetActive(false); } if (equippedGameObj != null) { equippedGameObj.transform.parent = kerbalModule.helmetTransform; } } else { DebugEx.Warning("Kerbal model doesn't have helmet transform: {0}", inventory); } } if (actorType == ActorType.Player) { UISoundPlayer.instance.Play(prefabModule.moveSndPath); } equipped = true; prefabModule.OnEquip(this); inventory.StartCoroutine(AlignEquippedPart()); }
public void Equip(ActorType actorType = ActorType.API) { // Only equip EVA kerbals. if (!prefabModule || inventory.invType != ModuleKISInventory.InventoryType.Eva) { Debug.LogWarningFormat("Cannot equip item from inventory type: {0}", inventory.invType); return; } if (quantity > 1) { ScreenMessaging.ShowPriorityScreenMessage(CannotEquipItemStackedMsg); UISounds.PlayBipWrong(); return; } Debug.LogFormat("Equip item {0} in mode {1}", availablePart.title, equipMode); // Check if the skill is needed. Skip the check in the sandbox modes. if (HighLogic.CurrentGame.Mode != Game.Modes.SANDBOX && HighLogic.CurrentGame.Mode != Game.Modes.SCIENCE_SANDBOX && !String.IsNullOrEmpty(prefabModule.equipSkill)) { bool skillFound = false; List <ProtoCrewMember> protoCrewMembers = inventory.vessel.GetVesselCrew(); foreach (var expEffect in protoCrewMembers[0].experienceTrait.Effects) { if (expEffect.ToString().Replace("Experience.Effects.", "") == prefabModule.equipSkill) { skillFound = true; break; } } if (!skillFound) { if (actorType == ActorType.Player) { ScreenMessaging.ShowPriorityScreenMessage( CannotEquipRestrictedToSkillMsg.Format(prefabModule.equipSkill)); UISounds.PlayBipWrong(); } return; } } // Check if slot is already occupied. if (equipSlot != null) { KIS_Item equippedItem = inventory.GetEquipedItem(equipSlot); if (equippedItem != null) { if (equippedItem.carriable && actorType == ActorType.Player) { ScreenMessaging.ShowPriorityScreenMessage( CannotEquipAlreadyCarryingMsg.Format(equipSlot, equippedItem.availablePart.title)); UISounds.PlayBipWrong(); return; } equippedItem.Unequip(); } } if (equipMode == EquipMode.Model) { GameObject modelGo = availablePart.partPrefab.FindModelTransform("model").gameObject; equippedGameObj = UnityEngine.Object.Instantiate(modelGo); foreach (Collider col in equippedGameObj.GetComponentsInChildren <Collider>()) { UnityEngine.Object.DestroyImmediate(col); } evaTransform = null; var skmrs = new List <SkinnedMeshRenderer>( inventory.part.GetComponentsInChildren <SkinnedMeshRenderer>()); foreach (SkinnedMeshRenderer skmr in skmrs) { if (skmr.name != prefabModule.equipMeshName) { continue; } foreach (Transform bone in skmr.bones) { if (bone.name == prefabModule.equipBoneName) { evaTransform = bone.transform; break; } } } if (!evaTransform) { Debug.LogError("evaTransform not found ! "); UnityEngine.Object.Destroy(equippedGameObj); return; } } if (equipMode == EquipMode.Part || equipMode == EquipMode.Physic) { evaTransform = null; var skmrs = new List <SkinnedMeshRenderer>( inventory.part.GetComponentsInChildren <SkinnedMeshRenderer>()); foreach (SkinnedMeshRenderer skmr in skmrs) { if (skmr.name != prefabModule.equipMeshName) { continue; } foreach (Transform bone in skmr.bones) { if (bone.name == prefabModule.equipBoneName) { evaTransform = bone.transform; break; } } } if (!evaTransform) { Debug.LogError("evaTransform not found ! "); return; } var alreadyEquippedPart = inventory.part.FindChildPart(availablePart.name); if (alreadyEquippedPart) { Debug.LogFormat("Part {0} already found on eva, use it as the item", availablePart.name); equippedPart = alreadyEquippedPart; // This magic is copied from the KervalEVA.OnVesselGoOffRails() method. // There must be at least 3 fixed frames delay before updating the colliders. AsyncCall.WaitForPhysics( equippedPart, 3, () => false, failure: () => OnEquippedPartReady(equippedPart)); if (equipMode == EquipMode.Part) { // Ensure the part doesn't have rigidbody and is not affected by physics. // The part may not like it. equippedPart.PhysicsSignificance = 1; // Disable physics on the part. UnityEngine.Object.Destroy(equippedPart.rb); } } else { Vector3 equipPos = evaTransform.TransformPoint(prefabModule.equipPos); Quaternion equipRot = evaTransform.rotation * Quaternion.Euler(prefabModule.equipDir); equippedPart = KIS_Shared.CreatePart( partNode, equipPos, equipRot, inventory.part, inventory.part, srcAttachNodeId: "srfAttach", onPartReady: OnEquippedPartReady, createPhysicsless: equipMode != EquipMode.Physic); } if (equipMode == EquipMode.Part) { equippedGameObj = equippedPart.gameObject; } } if (prefabModule.equipRemoveHelmet) { inventory.SetHelmet(false); } if (actorType == ActorType.Player) { UISoundPlayer.instance.Play(prefabModule.moveSndPath); } equipped = true; prefabModule.OnEquip(this); }
public void Equip(ActorType actorType = ActorType.API) { // Only equip EVA kerbals. if (!prefabModule || inventory.invType != ModuleKISInventory.InventoryType.Eva) { Debug.LogWarningFormat("Cannot equip item from inventory type: {0}", inventory.invType); return; } if (quantity > 1) { ScreenMessaging.ShowPriorityScreenMessage("Cannot equip stacked items"); UISounds.PlayBipWrong(); return; } Debug.LogFormat("Equip item {0} in mode {1}", availablePart.title, equipMode); // Check skill if needed. Skip the check in sandbox modes. if (HighLogic.CurrentGame.Mode != Game.Modes.SANDBOX && HighLogic.CurrentGame.Mode != Game.Modes.SCIENCE_SANDBOX && !String.IsNullOrEmpty(prefabModule.equipSkill)) { bool skillFound = false; List <ProtoCrewMember> protoCrewMembers = inventory.vessel.GetVesselCrew(); foreach (var expEffect in protoCrewMembers[0].experienceTrait.Effects) { if (expEffect.ToString().Replace("Experience.Effects.", "") == prefabModule.equipSkill) { skillFound = true; break; } } if (!skillFound) { if (actorType == ActorType.Player) { ScreenMessaging.ShowPriorityScreenMessage( "This item can only be used by a kerbal with the skill : {0}", prefabModule.equipSkill); UISounds.PlayBipWrong(); } return; } } // Check if slot is already occupied. if (equipSlot != null) { KIS_Item equippedItem = inventory.GetEquipedItem(equipSlot); if (equippedItem != null) { if (equippedItem.carriable && actorType == ActorType.Player) { ScreenMessaging.ShowPriorityScreenMessage( "Cannot equip item, slot <{0}> already used for carrying {1}", equipSlot, equippedItem.availablePart.title); UISounds.PlayBipWrong(); return; } equippedItem.Unequip(); } } if (equipMode == EquipMode.Model) { GameObject modelGo = availablePart.partPrefab.FindModelTransform("model").gameObject; equippedGameObj = UnityEngine.Object.Instantiate(modelGo); foreach (Collider col in equippedGameObj.GetComponentsInChildren <Collider>()) { UnityEngine.Object.DestroyImmediate(col); } evaTransform = null; var skmrs = new List <SkinnedMeshRenderer>( inventory.part.GetComponentsInChildren <SkinnedMeshRenderer>()); foreach (SkinnedMeshRenderer skmr in skmrs) { if (skmr.name != prefabModule.equipMeshName) { continue; } foreach (Transform bone in skmr.bones) { if (bone.name == prefabModule.equipBoneName) { evaTransform = bone.transform; break; } } } if (!evaTransform) { Debug.LogError("evaTransform not found ! "); UnityEngine.Object.Destroy(equippedGameObj); return; } } if (equipMode == EquipMode.Part || equipMode == EquipMode.Physic) { evaTransform = null; var skmrs = new List <SkinnedMeshRenderer>( inventory.part.GetComponentsInChildren <SkinnedMeshRenderer>()); foreach (SkinnedMeshRenderer skmr in skmrs) { if (skmr.name != prefabModule.equipMeshName) { continue; } foreach (Transform bone in skmr.bones) { if (bone.name == prefabModule.equipBoneName) { evaTransform = bone.transform; break; } } } if (!evaTransform) { Debug.LogError("evaTransform not found ! "); return; } var alreadyEquippedPart = inventory.part.FindChildPart(availablePart.name); if (alreadyEquippedPart) { Debug.LogFormat("Part {0} already found on eva, use it as the item", availablePart.name); equippedPart = alreadyEquippedPart; OnEquippedPartReady(equippedPart); } else { Vector3 equipPos = evaTransform.TransformPoint(prefabModule.equipPos); Quaternion equipRot = evaTransform.rotation * Quaternion.Euler(prefabModule.equipDir); equippedPart = KIS_Shared.CreatePart( partNode, equipPos, equipRot, inventory.part, inventory.part, srcAttachNodeId: "srfAttach", onPartReady: OnEquippedPartReady, createPhysicsless: equipMode != EquipMode.Physic); } if (equipMode == EquipMode.Part) { equippedGameObj = equippedPart.gameObject; } } if (prefabModule.equipRemoveHelmet) { inventory.SetHelmet(false); } if (actorType == ActorType.Player) { UISoundPlayer.instance.Play(prefabModule.moveSndPath); } equipped = true; prefabModule.OnEquip(this); }