/// <summary>Fixes null persistent fields in the module.</summary>
 /// <remarks>Used to prevent NREs in methods that persist KSP fields.</remarks>
 /// <param name="module">Module to fix.</param>
 public static void CleanupFieldsInModule(PartModule module)
 {
     // Ensure the module is awaken. Otherwise, any access to base fields list will result in NRE.
     // HACK: Accessing Fields property of a non-awaken module triggers NRE. If it happens then do
     // explicit awakening of the *base* module class.
     try {
         var unused = module.Fields.GetEnumerator();
     } catch {
         Logger.logWarning("WORKAROUND. Module {0} on part prefab {1} is not awaken. Call Awake on it",
                           module.GetType(), module.part);
         AwakePartModule(module);
     }
     foreach (var field in module.Fields)
     {
         var baseField = field as BaseField;
         if (baseField.isPersistant && baseField.GetValue(module) == null)
         {
             var proto    = new StandardOrdinaryTypesProto();
             var defValue = proto.ParseFromString("", baseField.FieldInfo.FieldType);
             Logger.logWarning("WORKAROUND. Found null field {0} in module prefab {1},"
                               + " fixing to default value of type {2}: {3}",
                               baseField.name,
                               module.moduleName,
                               baseField.FieldInfo.FieldType,
                               defValue);
             baseField.SetValue(defValue, module);
         }
     }
 }
예제 #2
0
        /// <summary>Makes a game object to represent currently dragging assembly.</summary>
        /// <remarks>It's a very expensive operation.</remarks>
        static void MakePointer()
        {
            DestroyPointer();

            // Make pointer node transformations.
            if (pointerNodeTransform)
            {
                pointerNodeTransform.gameObject.DestroyGameObject();
            }
            pointerNodeTransform = new GameObject("KISPointerPartNode").transform;

            // Deatch will decouple from the parent so, ask to ignore it when looking for the nodes.
            attachNodes =
                KIS_Shared.GetAvailableAttachNodes(partToAttach, ignoreAttachedPart: partToAttach.parent);
            if (!attachNodes.Any())
            {
                //TODO: When there are no nodes try finding ones in the parent or in the children.
                // Ideally, the caller should have checked if this part has free nodes. Now the only
                // way is to pick *any* node. The surface one always exists so, it's a good
                // candidate. Though, for many details it may result in a weird representation.
                Logger.logError("Part {0} has no free nodes, use {1}",
                                partToAttach, partToAttach.srfAttachNode);
                attachNodes.Add(partToAttach.srfAttachNode);
            }
            attachNodeIndex = 0; // Expect that first node is the best default.

            UpdatePointerAttachNode();

            // Make pointer renderer.
            var combines = new List <CombineInstance>();

            CollectMeshesFromAssembly(partToAttach, combines);

            // Create one filter per mesh in the hierarhcy. Simple combining all meshes into one
            // larger mesh may have weird representation artifacts on different video cards.
            pointer = new GameObject("KISPointer");
            foreach (var combine in combines)
            {
                var mesh = new Mesh();
                mesh.CombineMeshes(new[] { combine });
                var childObj = new GameObject("KISPointerChildMesh");

                var meshRenderer = childObj.AddComponent <MeshRenderer>();
                meshRenderer.shadowCastingMode = ShadowCastingMode.Off;
                meshRenderer.receiveShadows    = false;

                var filter = childObj.AddComponent <MeshFilter>();
                filter.sharedMesh = mesh;

                childObj.transform.parent = pointer.transform;
            }
            allModelMr = pointer.GetComponentsInChildren <MeshRenderer>().ToList();
            foreach (var mr in allModelMr)
            {
                mr.material = new Material(Shader.Find("Transparent/Diffuse"));
            }
            pointerNodeTransform.parent = pointer.transform;

            Logger.logInfo("New pointer created");
        }
예제 #3
0
 public void Unequip()
 {
     if (!prefabModule)
     {
         return;
     }
     if (equipMode == EquipMode.Model)
     {
         UnityEngine.Object.Destroy(equippedGameObj);
         if (prefabModule.equipRemoveHelmet)
         {
             inventory.SetHelmet(true);
         }
     }
     if (equipMode == EquipMode.Part || equipMode == EquipMode.Physic)
     {
         Logger.logInfo("Update config node of equipped part: {0}", availablePart.title);
         partNode.ClearData();
         KIS_Shared.PartSnapshot(equippedPart).CopyTo(partNode);
         equippedPart.Die();
     }
     evaTransform    = null;
     equippedPart    = null;
     equippedGameObj = null;
     equipped        = false;
     PlaySound(prefabModule.moveSndPath);
     prefabModule.OnUnEquip(this);
 }
예제 #4
0
        public Dictionary <AttachNode, List <string> > GetMounts()
        {
            var        mounts = new Dictionary <AttachNode, List <string> >();
            ConfigNode node   = KIS_Shared.GetBaseConfigNode(this);

            foreach (ConfigNode mountNode in node.GetNodes("MOUNT"))
            {
                if (mountNode.HasValue("attachNode") && mountNode.HasValue("allowedPartName"))
                {
                    string     attachNodeName = mountNode.GetValue("attachNode");
                    AttachNode an             = this.part.FindAttachNode(attachNodeName);
                    if (an == null)
                    {
                        Logger.logError("GetMountNodes - Node : {0} not found !", attachNodeName);
                        continue;
                    }

                    var allowedPartNames = new List <string>();
                    foreach (string partName in mountNode.GetValues("allowedPartName"))
                    {
                        allowedPartNames.Add(partName.Replace('_', '.'));
                    }
                    mounts.Add(an, allowedPartNames);
                }
            }
            return(mounts);
        }
예제 #5
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();
             }
         }
     }
 }
예제 #6
0
 public static void StopPointer()
 {
     Logger.logInfo("StopPointer()");
     running = false;
     ResetMouseOver();
     InputLockManager.RemoveControlLock("KISpointer");
     DestroyPointer();
     allowedAttachmentParts = allowedAttachmentParts; // Clear selection.
 }
예제 #7
0
 void Awake()
 {
     audioGo = new GameObject();
     Logger.logInfo("Loading UI sounds for KIS...");
     InitSound(bipWrongSndPath, out audioBipWrong);
     InitSound(clickSndPath, out audioClick);
     InitSound(attachPartSndPath, out audioAttach);
     instance = this;
 }
예제 #8
0
        void InitConfig(AvailablePart availablePart, ModuleKISInventory inventory, float quantity)
        {
            this.inventory = inventory;
            this.quantity  = quantity;
            prefabModule   = availablePart.partPrefab.GetComponent <ModuleKISItem>();
            volume         = KIS_Shared.GetPartVolume(availablePart);
            cost           = GetCost();

            // Set launchID
            if (partNode.HasValue("launchID"))
            {
                if (int.Parse(this.partNode.GetValue("launchID")) == 0)
                {
                    partNode.SetValue("launchID", this.inventory.part.launchID.ToString(), true);
                }
            }
            else
            {
                partNode.SetValue("launchID", this.inventory.part.launchID.ToString(), true);
            }

            if (prefabModule)
            {
                equipable           = prefabModule.equipable;
                stackable           = prefabModule.stackable;
                equipSlot           = prefabModule.equipSlot;
                usableFromEva       = prefabModule.usableFromEva;
                usableFromContainer = prefabModule.usableFromContainer;
                usableFromPod       = prefabModule.usableFromPod;
                usableFromEditor    = prefabModule.usableFromEditor;
                carriable           = prefabModule.carriable;
            }
            int nonStackableModule = 0;

            foreach (PartModule pModule in availablePart.partPrefab.Modules)
            {
                if (!KISAddonConfig.stackableModules.Contains(pModule.moduleName))
                {
                    nonStackableModule++;
                }
            }
            if (nonStackableModule == 0 && GetResources().Count == 0)
            {
                Logger.logInfo(
                    "No non-stackable module or a resource found on the part, set the item as stackable");
                stackable = true;
            }
            if (KISAddonConfig.stackableList.Contains(availablePart.name) ||
                availablePart.name.IndexOf('.') != -1 &&
                KISAddonConfig.stackableList.Contains(availablePart.name.Replace('.', '_')))
            {
                Logger.logInfo("Part name present in settings.cfg (node StackableItemOverride),"
                               + " force item as stackable");
                stackable = true;
            }
        }
 /// <summary>Adds the specified items into the inventory.</summary>
 /// <param name="inventory">An inventory to add items into.</param>
 /// <param name="itemNames">A list of names of the parts to add.</param>
 void AddItems(ModuleKISInventory inventory, List<string> itemNames) {
   foreach (var defItemName in itemNames) {
     var defPart = PartLoader.getPartInfoByName(defItemName);
     if (defPart != null) {
       inventory.AddItem(defPart.partPrefab);
     } else {
       Logger.logError("Cannot make item {0} specified as a default for the pod seat",
                       defItemName);
     }
   }
 }
예제 #10
0
 // Resets item state when joint is broken.
 // A callback from MonoBehaviour.
 void OnJointBreak(float breakForce)
 {
     if (staticAttached)
     {
         Logger.logWarning("A static joint has just been broken! Force: {0}", breakForce);
     }
     else
     {
         Logger.logWarning("A fixed joint has just been broken! Force: {0}", breakForce);
     }
     GroundDetach();
 }
예제 #11
0
 public virtual void OnPartUnpack()
 {
     if (allowStaticAttach == ItemAttachMode.Disabled || useExternalStaticAttach)
     {
         return;
     }
     if (staticAttached)
     {
         Logger.logInfo("Re-attach static object (OnPartUnpack)");
         GroundAttach();
     }
 }
예제 #12
0
 public void GroundDetach()
 {
     if (staticAttached)
     {
         Logger.logInfo("Removing static rigidbody and fixed joint on: {0}", this.part.partInfo.title);
         if (staticAttachJoint)
         {
             Destroy(staticAttachJoint);
         }
         staticAttachJoint = null;
         staticAttached    = false;
     }
 }
예제 #13
0
 /// <summary>Sets current pointer visible state.</summary>
 /// <remarks>
 /// Method expects all or none of the objects in the pointer to be visible: pointer
 /// visiblity state is determined by checking the first <c>MeshRenderer</c> only.
 /// </remarks>
 /// <param name="isVisible">New state.</param>
 /// <exception cref="InvalidOperationException">If pointer doesn't exist.</exception>
 private static void SetPointerVisible(bool isVisible)
 {
     foreach (var mr in pointer.GetComponentsInChildren <MeshRenderer>())
     {
         if (mr.enabled == isVisible &&
             mr.material.renderQueue == KIS_Shared.HighlighedPartRenderQueue)
         {
             return; // Abort if current state is already up to date.
         }
         mr.enabled = isVisible;
         mr.material.renderQueue = KIS_Shared.HighlighedPartRenderQueue;
     }
     Logger.logInfo("Pointer state set to: visibility={0}", isVisible);
 }
예제 #14
0
        public void Awake()
        {
            ConfigAccessor.ReadFieldsInType(GetType(), this);
            ConfigAccessor.ReadFieldsInType(typeof(ModuleKISInventory), instance: null);

            // Set inventory module for every eva kerbal
            Logger.logInfo("Set KIS config...");
            ConfigNode nodeSettings = GameDatabase.Instance.GetConfigNode("KIS/settings/KISConfig");

            if (nodeSettings == null)
            {
                Logger.logError("KIS settings.cfg not found or invalid !");
                return;
            }

            // Male Kerbal.
            UpdateEvaPrefab(PartLoader.getPartInfoByName(MaleKerbalEva), nodeSettings);
            // Female Kerbal.
            UpdateEvaPrefab(PartLoader.getPartInfoByName(FemaleKerbalEva), nodeSettings);

            // Set inventory module for every pod with crew capacity.
            Logger.logInfo("Loading pod inventories...");
            foreach (AvailablePart avPart in PartLoader.LoadedPartsList)
            {
                if (avPart.name == MaleKerbalEva || avPart.name == FemaleKerbalEva ||
                    avPart.name == RdKerbalEva ||
                    !avPart.partPrefab || avPart.partPrefab.CrewCapacity < 1)
                {
                    continue;
                }

                Logger.logInfo("Found part with CrewCapacity: {0}", avPart.name);
                for (int i = 0; i < avPart.partPrefab.CrewCapacity; i++)
                {
                    try {
                        var moduleInventory =
                            avPart.partPrefab.AddModule(typeof(ModuleKISInventory).Name) as ModuleKISInventory;
                        KIS_Shared.AwakePartModule(moduleInventory);
                        SetInventoryConfig(moduleInventory, nodeSettings);
                        moduleInventory.podSeat = i;
                        moduleInventory.invType = ModuleKISInventory.InventoryType.Pod;
                        Logger.logInfo("Pod inventory module(s) for seat {0} loaded successfully", i);
                    } catch {
                        Logger.logError("Pod inventory module(s) for seat {0} can't be loaded!", i);
                    }
                }
            }
        }
예제 #15
0
        /// <summary>Destroyes object(s) allocated to represent a pointer.</summary>
        /// <remarks>When making pointer for a complex hierarchy a lot of different resources may be
        /// allocated/dropped. Destroying each one of them can be too slow so, cleanup is done in
        /// one call to <c>UnloadUnusedAssets()</c>.
        /// <para>This method also destroys <see cref="pointerNodeTransform"/>.</para>
        /// </remarks>
        private static void DestroyPointer()
        {
            if (!pointer)
            {
                return; // Nothing to do.
            }
            pointer.DestroyGameObject();
            pointer = null;
            pointerNodeTransform.gameObject.DestroyGameObject();
            pointerNodeTransform = null;
            allModelMr.Clear();

            // On large assemblies memory consumption can be significant. Reclaim it.
            Resources.UnloadUnusedAssets();
            Logger.logInfo("Pointer destroyed");
        }
예제 #16
0
    void InitSound(string clipPath, out AudioSource source)
    {
        Logger.logInfo("Loading clip: {0}", clipPath);
        source              = audioGo.AddComponent <AudioSource>();
        source.volume       = GameSettings.UI_VOLUME;
        source.spatialBlend = 0; //set as 2D audiosource

        if (GameDatabase.Instance.ExistsAudioClip(clipPath))
        {
            source.clip = GameDatabase.Instance.GetAudioClip(clipPath);
        }
        else
        {
            Logger.logError("Cannot locate clip: {0}", clipPath);
        }
    }
예제 #17
0
        // Called once when script is loaded; use to initialize variables and state
        void Awake()
        {
            audioGo                    = new GameObject();
            audioBipWrong              = audioGo.AddComponent <AudioSource>();
            audioBipWrong.volume       = GameSettings.UI_VOLUME;
            audioBipWrong.spatialBlend = 0; //set as 2D audiosource

            if (GameDatabase.Instance.ExistsAudioClip(KIS_Shared.bipWrongSndPath))
            {
                audioBipWrong.clip = GameDatabase.Instance.GetAudioClip(KIS_Shared.bipWrongSndPath);
            }
            else
            {
                Logger.logError("Awake(AttachPointer) Bip wrong sound not found in the game database !");
            }
        }
예제 #18
0
        /// <summary>Fixes all structural links to another vessel(s).</summary>
        /// <remarks>
        /// Normally compound parts should handle decoupling themselves but sometimes they do it
        /// horribly wrong. For instance, stock strut connector tries to restore connection when
        /// part is re-attached to the former vessel which may produce a collision. This method
        /// deletes all compound parts with target pointing to a different vessel.
        /// </remarks>
        /// <param name="vessel">Vessel to fix links for.</param>
        // TODO: Break the link instead of destroying the part.
        // TODO: Handle KAS and other popular plugins connectors.
        public static void CleanupExternalLinks(Vessel vessel)
        {
            var parts = vessel.parts.FindAll(p => p is CompoundPart);

            Logger.logInfo("Check {0} compound part(s) in vessel: {1}", parts.Count(), vessel);
            foreach (var part in parts)
            {
                var compoundPart = part as CompoundPart;
                if (compoundPart.target && compoundPart.target.vessel != vessel)
                {
                    Logger.logInfo("Destroy compound part '{0}' which links '{1}' to '{2}'",
                                   compoundPart, compoundPart.parent, compoundPart.target);
                    compoundPart.Die();
                }
            }
        }
예제 #19
0
        /// <summary>Makes a call to <c>Awake()</c> method of the part module.</summary>
        /// <remarks>Modules added to prefab via <c>AddModule()</c> call are not get activated as they
        /// would if activated by the Unity core. As a result some vital fields may be left uninitialized
        /// which may result in an NRE later when working with the prefab (e.g. making a part snapshot).
        /// This method finds and invokes method <c>Awake</c> via reflection which is normally done by
        /// Unity.
        /// <para><b>IMPORTANT!</b> This method cannot awake a module! To make the things right every
        /// class in the hierarchy should get its <c>Awake</c> called. This method only calls <c>Awake</c>
        /// method on <c>PartModule</c> parent class which is not enough to do a complete awakening.
        /// </para>
        /// <para>This is a HACK since <c>Awake()</c> method is not supposed to be called by anyone but
        /// Unity. For now it works fine but one day it may awake the kraken.</para>
        /// </remarks>
        /// <param name="module">Module instance to awake.</param>
        public static void AwakePartModule(PartModule module)
        {
            // Private method can only be accessed via reflection when requested on the class that declares
            // it. So, don't use type of the argument and specify it explicitly.
            var moduleAwakeMethod = typeof(PartModule).GetMethod(
                "Awake", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            if (moduleAwakeMethod != null)
            {
                moduleAwakeMethod.Invoke(module, new object[] {});
            }
            else
            {
                Logger.logError("Cannot find Awake() method on {0}. Skip awakening of component: {1}",
                                module.GetType(), module.GetType());
            }
        }
예제 #20
0
        /// <summary>Goes thru part assembly and collects all meshes in the hierarchy.</summary>
        /// <remarks>
        /// Returns shared meshes with the right transformations. No new objects are created.
        /// </remarks>
        /// <param name="assembly">An assembly to collect meshes from.</param>
        /// <param name="meshCombines">[out] Collected meshes.</param>
        /// <param name="worldTransform">A world transformation matrix to apply to every mesh after
        ///     it's translated into world's coordinates. If <c>null</c> then coordinates will be
        ///     calculated relative to the root part of the assembly.</param>
        private static void CollectMeshesFromAssembly(Part assembly,
                                                      ICollection <CombineInstance> meshCombines,
                                                      Matrix4x4?worldTransform = null)
        {
            // Always use world transformation from the root.
            var rootWorldTransform = worldTransform ?? assembly.transform.localToWorldMatrix.inverse;

            // Get all meshes from the part's model.
            var meshFilters = assembly.FindModelComponents <MeshFilter>();

            if (meshFilters.Count > 0)
            {
                Logger.logInfo("Found {0} children meshes in: {1}", meshFilters.Count, assembly);
                foreach (var meshFilter in meshFilters)
                {
                    var combine = new CombineInstance();
                    combine.mesh      = meshFilter.sharedMesh;
                    combine.transform = rootWorldTransform * meshFilter.transform.localToWorldMatrix;
                    meshCombines.Add(combine);
                }
            }

            // Skinned meshes are baked on every frame before rendering. Bake them to get current mesh
            // state.
            var skinnedMeshRenderers = assembly.FindModelComponents <SkinnedMeshRenderer>();

            if (skinnedMeshRenderers.Count > 0)
            {
                Logger.logInfo("Found {0} skinned meshes in: {1}", skinnedMeshRenderers.Count, assembly);
                foreach (var skinnedMeshRenderer in skinnedMeshRenderers)
                {
                    var combine = new CombineInstance();
                    combine.mesh = new Mesh();
                    skinnedMeshRenderer.BakeMesh(combine.mesh);
                    combine.transform = rootWorldTransform * skinnedMeshRenderer.transform.localToWorldMatrix;
                    meshCombines.Add(combine);
                }
            }

            // Collect meshes from the children parts.
            foreach (Part child in assembly.children)
            {
                CollectMeshesFromAssembly(child, meshCombines, worldTransform: rootWorldTransform);
            }
        }
예제 #21
0
        IEnumerator WaitAndStaticAttach()
        {
            // Wait for part to become active in case of it came from inventory.
            while (!part.started && part.State != PartStates.DEAD)
            {
                yield return(new WaitForFixedUpdate());
            }
            part.vessel.Landed = true;

            Logger.logInfo("Create fixed joint attached to the world");
            if (staticAttachJoint)
            {
                Destroy(staticAttachJoint);
            }
            staticAttachJoint             = part.gameObject.AddComponent <FixedJoint>();
            staticAttachJoint.breakForce  = staticAttachBreakForce;
            staticAttachJoint.breakTorque = staticAttachBreakForce;
        }
예제 #22
0
        public static void CouplePart(Part srcPart, Part tgtPart, string srcAttachNodeID = null,
                                      AttachNode tgtAttachNode = null)
        {
            // Node links
            if (srcAttachNodeID != null)
            {
                if (srcAttachNodeID == "srfAttach")
                {
                    Logger.logInfo("Attach type: {0} | ID : {1}",
                                   srcPart.srfAttachNode.nodeType, srcPart.srfAttachNode.id);
                    srcPart.attachMode = AttachModes.SRF_ATTACH;
                    srcPart.srfAttachNode.attachedPart = tgtPart;
                }
                else
                {
                    AttachNode srcAttachNode = srcPart.FindAttachNode(srcAttachNodeID);
                    if (srcAttachNode != null)
                    {
                        Logger.logInfo("Attach type : {0} | ID : {1}",
                                       srcPart.srfAttachNode.nodeType, srcAttachNode.id);
                        srcPart.attachMode         = AttachModes.STACK;
                        srcAttachNode.attachedPart = tgtPart;
                        if (tgtAttachNode != null)
                        {
                            tgtAttachNode.attachedPart = srcPart;
                        }
                        else
                        {
                            Logger.logWarning("Target node is null");
                        }
                    }
                    else
                    {
                        Logger.logError("Source attach node not found !");
                    }
                }
            }
            else
            {
                Logger.logWarning("Missing source attach node !");
            }

            srcPart.Couple(tgtPart);
        }
 /// <summary>Adds default items to the pod's seats.</summary>
 /// <remarks>Items are only added to a part created in the editor. Thus, reacting on the editor
 /// event.</remarks>
 /// <param name="type">Unused.</param>
 /// <param name="p">A target part.</param>
 void OnEditPartCreate(ConstructionEventType type, Part p) {
   if (type != ConstructionEventType.PartCreated && type != ConstructionEventType.PartCopied) {
     return;
   }
   var inventories = p.GetComponents<ModuleKISInventory>();
   foreach (var inventory in inventories) {
     if (inventory.podSeat != -1 && ModuleKISInventory.defaultItemsForAllSeats.Count > 0) {
       Logger.logInfo(
           "Adding default item(s) into seat's {0} inventory of part {1}: {2}",
           inventory.podSeat, p.name, Logger.C2S(ModuleKISInventory.defaultItemsForAllSeats));
       AddItems(inventory, ModuleKISInventory.defaultItemsForAllSeats);
     }
     if (inventory.podSeat == 0 && ModuleKISInventory.defaultItemsForTheFirstSeat.Count > 0) {
       Logger.logInfo("Adding default item(s) into the first seat of part {0}: {1}",
                      p.name, Logger.C2S(ModuleKISInventory.defaultItemsForTheFirstSeat));
       AddItems(inventory, ModuleKISInventory.defaultItemsForTheFirstSeat);
     }
   }
 }
예제 #24
0
        public static void StartPointer(Part partToMoveAndAttach, OnPointerClick pClick,
                                        OnPointerState pState, Transform from = null)
        {
            if (!running)
            {
                Logger.logInfo("StartPointer()");
                customRot        = Vector3.zero;
                aboveDistance    = 0;
                partToAttach     = partToMoveAndAttach;
                sourceTransform  = from;
                running          = true;
                SendPointerClick = pClick;
                SendPointerState = pState;

                MakePointer();

                InputLockManager.SetControlLock(ControlTypes.ALLBUTCAMERAS, "KISpointer");
                allowedAttachmentParts = allowedAttachmentParts; // Apply selection.
            }
        }
예제 #25
0
 public void OnSave(ConfigNode node)
 {
     node.AddValue("partName", this.availablePart.name);
     node.AddValue("slot", slot);
     node.AddValue("quantity", quantity);
     node.AddValue("equipped", equipped);
     node.AddValue("resourceMass", resourceMass);
     node.AddValue("contentMass", contentMass);
     node.AddValue("contentCost", contentCost);
     if (inventoryName != "")
     {
         node.AddValue("inventoryName", inventoryName);
     }
     if (equipped && (equipMode == EquipMode.Part || equipMode == EquipMode.Physic))
     {
         Logger.logInfo("Update config node of equipped part: {0}", this.availablePart.title);
         partNode.ClearData();
         KIS_Shared.PartSnapshot(equippedPart).CopyTo(partNode);
     }
     partNode.CopyTo(node.AddNode("PART"));
 }
예제 #26
0
        void UpdateEvaPrefab(AvailablePart avPart, ConfigNode nodeSettings)
        {
            var prefab = avPart.partPrefab;

            // Adding module to EVA may cause an NPE but module update will still work.
            try {
                prefab.AddModule(typeof(ModuleKISInventory).Name);
            } catch (Exception ex) {
                Logger.logInfo(
                    "NOT A BUG! Ignoring error while adding ModuleKISInventory to {0}: {1}", prefab, ex);
            }
            try {
                prefab.AddModule(typeof(ModuleKISPickup).Name);
            } catch (Exception ex) {
                Logger.logInfo("NOT A BUG! Ignoring error adding ModuleKISPickup to {0}: {1}", prefab, ex);
            }

            // Setup inventory module for eva.
            var evaInventory = prefab.GetComponent <ModuleKISInventory>();

            KIS_Shared.AwakePartModule(evaInventory);
            if (evaInventory)
            {
                SetInventoryConfig(evaInventory, nodeSettings);
                evaInventory.invType = ModuleKISInventory.InventoryType.Eva;
                Logger.logInfo("Eva inventory module loaded successfully");
            }

            // Load KSP fields for ModuleKISPickup module.
            var nodeEvaPickup = nodeSettings.GetNode("EvaPickup");
            var evaPickup     = prefab.GetComponent <ModuleKISPickup>();

            KIS_Shared.AwakePartModule(evaPickup);
            if (evaPickup && nodeEvaPickup != null)
            {
                var fields = new BaseFieldList(evaPickup);
                fields.Load(nodeEvaPickup);
                Logger.logInfo("Eva pickup module loaded successfully");
            }
        }
예제 #27
0
        /// <summary>Walks thru all modules in the part and fixes null persistent fields.</summary>
        /// <remarks>Used to prevent NREs in methods that persist KSP fields.
        /// <para>Bad modules that cannot be fixed will be dropped which may make the part to be not
        /// behaving as expected. It's guaranteed that <i>stock</i> modules that need fixing will be
        /// fixed successfully. So, failures are only expected on the modules from the third-parties mods.
        /// </para></remarks>
        /// <param name="part">Prefab to fix.</param>
        public static void CleanupModuleFieldsInPart(Part part)
        {
            var badModules = new List <PartModule>();

            foreach (var moduleObj in part.Modules)
            {
                var module = moduleObj as PartModule;
                try {
                    CleanupFieldsInModule(module);
                } catch {
                    badModules.Add(module);
                }
            }
            // Cleanup modules that block KIS. It's a bad thing to do but not working KIS is worse.
            foreach (var moduleToDrop in badModules)
            {
                Logger.logError(
                    "Module on part prefab {0} is setup improperly: name={1}, type={2}. Drop it!",
                    part, moduleToDrop.moduleName, moduleToDrop.GetType());
                part.RemoveModule(moduleToDrop);
            }
        }
        public override void OnItemUse(KIS_Item item, KIS_Item.UseFrom useFrom)
        {
            pageList.Clear();
            ConfigNode node = KIS_Shared.GetBaseConfigNode(this);

            foreach (string page in node.GetValues("page"))
            {
                pageList.Add(page);
            }
            if (pageList.Count > 0)
            {
                pageIndex   = 0;
                pageTotal   = pageList.Count;
                pageTexture = GameDatabase.Instance.GetTexture(pageList[0], false);
                showPage    = true;
                item.inventory.PlaySound(bookOpenSndPath, false, true);
            }
            else
            {
                Logger.logError("The book has no pages configured");
            }
        }
예제 #29
0
        public void Drop(Part fromPart = null)
        {
            Logger.logInfo("Drop item");
            if (fromPart == null)
            {
                fromPart = inventory.part;
            }
            Quaternion rot;
            Vector3    pos;

            if (prefabModule)
            {
                rot = evaTransform.rotation * Quaternion.Euler(prefabModule.equipDir);
                pos = evaTransform.TransformPoint(prefabModule.equipPos);
            }
            else
            {
                rot = inventory.part.transform.rotation;
                pos = inventory.part.transform.position + new Vector3(0, 1, 0);
            }
            KIS_Shared.CreatePart(partNode, pos, rot, fromPart);
            StackRemove(1);
        }
예제 #30
0
 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);
     }
 }