/// <summary> /// Clones an item prefab and returns the clone to you. Caches the original prefab for other mods or other custom items to reference. /// </summary> /// <param name="cloneTargetID">The Item ID of the Item you want to clone from</param> /// <param name="newID">The new Item ID for your cloned item. Can be the same as the target, will overwrite.</param> /// <param name="name">Only used for the gameObject name, not the actual Item Name. This is the name thats used in Debug Menus.</param> /// <param name="template">[Optional] If provided, the item component may be changed to match the type of the template if necessary.</param> /// <returns>Your cloned Item prefab</returns> public static Item CreateCustomItem(int cloneTargetID, int newID, string name, SL_Item template = null) { Item original = GetOriginalItemPrefab(cloneTargetID); if (!original) { SL.LogError("CustomItems.CreateCustomItem - Error! Could not find the clone target Item ID: " + cloneTargetID); return(null); } Item item; original.transform.ResetLocal(); // modifying an existing item if (newID == cloneTargetID) { // Modifying the original prefab for the first time. Cache it in case someone else wants the true original. if (!OrigItemPrefabs.ContainsKey(newID)) { var cached = GameObject.Instantiate(original.gameObject).GetComponent <Item>(); cached.gameObject.SetActive(false); GameObject.DontDestroyOnLoad(cached.gameObject); cached.transform.parent = SL.CloneHolder; OrigItemPrefabs.Add(cached.ItemID, cached); } // apply to the original item prefab. this ensures direct prefab references to this item reflect the changes. item = original; } else // making a new item { item = GameObject.Instantiate(original.gameObject).GetComponent <Item>(); item.gameObject.SetActive(false); item.gameObject.name = newID + "_" + name; // fix for name and description localization SetNameAndDescription(item, original.Name, original.Description); } if (template != null) { var gameType = Serializer.GetGameType(template.GetType()); if (gameType != item.GetType()) { item = UnityHelpers.FixComponentType(gameType, item) as Item; } } item.ItemID = newID; SetItemID(newID, item); // Do this so that any changes we make are not destroyed on scene changes. // This is needed whether this is a clone or a new item. GameObject.DontDestroyOnLoad(item.gameObject); item.transform.parent = SL.CloneHolder; item.gameObject.SetActive(true); return(item); }
/// <summary> /// Searches the provided AssetBundle for folders in the expected format, and applies textures to the corresponding Item. /// Each item must have its own sub-folder, where the name of this folder starts with the Item's ItemID. /// The folder name can have anything else after the ID, but it must start with the ID. /// Eg., '2000010_IronSword\' would be valid to set the textures on the Iron Sword. /// The textures should be placed inside this folder and should match the Shader Layer names of the texture (the same way you set Item textures from a folder). /// </summary> /// <param name="bundle">The AssetBundle to apply Textures from.</param> public static void ApplyTexturesFromAssetBundle(AssetBundle bundle) { // Keys: Item IDs // Values: List of Textures/Sprites to apply to the item // The ItemTextures Value Key is the Material name, and the List<Texture2D> are the actual textures. var itemTextures = new Dictionary <int, Dictionary <string, List <Texture2D> > >(); var icons = new Dictionary <int, List <Sprite> >(); string[] names = bundle.GetAllAssetNames(); foreach (var name in names) { try { SL.Log("Loading texture from AssetBundle, path: " + name); Texture2D tex = bundle.LoadAsset <Texture2D>(name); // cleanup the name (remove ".png") tex.name = tex.name.Replace(".png", ""); // Split the assetbundle path by forward slashes string[] splitPath = name.Split('/'); // Get the ID from the first 7 characters of the path int id = int.Parse(splitPath[1].Substring(0, 7)); // Identify icons by name if (tex.name.Contains("icon")) { if (!icons.ContainsKey(id)) { icons.Add(id, new List <Sprite>()); } Sprite sprite; if (tex.name.Contains("skill")) { sprite = CustomTextures.CreateSprite(tex, CustomTextures.SpriteBorderTypes.SkillTreeIcon); } else { sprite = CustomTextures.CreateSprite(tex, CustomTextures.SpriteBorderTypes.ItemIcon); } icons[id].Add(sprite); } else // is not an icon { var mat = ""; if (splitPath[2] == "textures") { mat = splitPath[3]; } else { mat = splitPath[2]; } if (!itemTextures.ContainsKey(id)) { itemTextures.Add(id, new Dictionary <string, List <Texture2D> >()); } if (!itemTextures[id].ContainsKey(mat)) { itemTextures[id].Add(mat, new List <Texture2D>()); } itemTextures[id][mat].Add(tex); } } catch (InvalidCastException) { // suppress } catch (Exception ex) { SL.Log("Exception loading textures from asset bundle!"); SL.Log(ex.Message); SL.Log(ex.StackTrace); } } // Apply material textures foreach (var entry in itemTextures) { if (ResourcesPrefabManager.Instance.GetItemPrefab(entry.Key) is Item item) { SL_Item.ApplyTexAndMats(entry.Value, null, item); } } // Apply icons foreach (var entry in icons) { if (ResourcesPrefabManager.Instance.GetItemPrefab(entry.Key) is Item item) { ApplyIconsByName(entry.Value.ToArray(), item); } } }
/// <summary> /// Simple method to apply a SL_Item template. /// If defining a custom item after SL.OnPacksLoaded it will be applied instantly, otherwise it uses a callback to be applied later. /// </summary> /// <param name="template"></param> /// <returns>Your new custom item (or the original item, if modifying an existing one)</returns> public static Item CreateCustomItem(SL_Item template) { return(CreateCustomItem(template.Target_ItemID, template.New_ItemID, template.Name, template)); }