Example #1
0
        /// <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);
        }
Example #2
0
 /// <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();
             }
         }
     }
 }
Example #3
0
        /// <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);
            }
        }
Example #5
0
 /// <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();
             }
         }
     }
 }
Example #6
0
 /// <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();
             }
         }
     }
 }
Example #7
0
        /// <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);
        }
Example #8
0
        /// <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);
        }
Example #9
0
 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));
     }
 }
Example #10
0
 /// <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)));
 }
Example #11
0
        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);
        }
Example #12
0
        /// <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);
        }
Example #13
0
        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);
            }
        }
Example #14
0
        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);
        }
Example #15
0
        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);
     }
 }
Example #17
0
        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);
                }
            }
        }
Example #18
0
        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);
        }
Example #19
0
 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);
                         }
                     }
                 }
             }
         }
     }
 }
Example #20
0
        /// <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);
        }
Example #21
0
 /// <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);
 }
Example #22
0
        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());
        }
Example #23
0
        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);
        }
Example #24
0
        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);
        }