/// <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"); }
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); }
/// <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); } } }
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); } } } }
// 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 !"); } }
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); } }
/// <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()); } }
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); }
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"); } }
/// <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 static bool createFXSound(Part part, FXGroup group, string sndPath, bool loop, float maxDistance = 30f) { group.audio = part.gameObject.AddComponent <AudioSource>(); group.audio.volume = GameSettings.SHIP_VOLUME; group.audio.rolloffMode = AudioRolloffMode.Linear; group.audio.dopplerLevel = 0f; group.audio.spatialBlend = 1f; group.audio.maxDistance = maxDistance; group.audio.loop = loop; group.audio.playOnAwake = false; if (GameDatabase.Instance.ExistsAudioClip(sndPath)) { group.audio.clip = GameDatabase.Instance.GetAudioClip(sndPath); return(true); } else { Logger.logError("Sound not found in the game database !"); ScreenMessaging.ShowPriorityScreenMessageWithTimeout( 10, "Sound file : {0} has not been found, please check your KIS installation !", sndPath); return(false); } }
public void Equip() { // Only equip EVA kerbals. if (!prefabModule || !inventory.vessel.isEVA) { return; } Logger.logInfo("Equip item {0}", this.availablePart.name); // 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) { 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); }