static void Postfix(ref CardFrameUI __instance, CardState cardState, List <AbstractSpriteSelector> ___spriteSelectors) { try { if (cardState.GetLinkedClassID() == null) { return; } List <Sprite> cardFrame; if (CustomClassManager.CustomClassFrame.TryGetValue(cardState.GetLinkedClassID(), out cardFrame)) { foreach (AbstractSpriteSelector spriteSelector in ___spriteSelectors) { switch (spriteSelector) { case ClassSpriteSelector classSpriteSelector: foreach (var image in classSpriteSelector.gameObject.GetComponents <Image>()) { image.sprite = cardState.GetCardType() == CardType.Monster ? cardFrame[0] : cardFrame[1]; } continue; } } } } catch (Exception) { Trainworks.Log(BepInEx.Logging.LogLevel.Error, "TryGetValue is a dumb function."); } }
/// <summary> /// Imports new data to the English Localization from a CSV string with separators ';'. /// Required columns are 'Keys', 'Type', 'Plural', 'Group', 'Desc', 'Descriptions' /// </summary> public static void ImportCSV(string path, char Separator = ',') { string CSVstring = ""; var localPath = Path.GetDirectoryName(new Uri(Assembly.GetCallingAssembly().CodeBase).LocalPath); Trainworks.Log(BepInEx.Logging.LogLevel.All, "File: " + Path.Combine(localPath, path)); try { // Open the text file using a stream reader. using (StreamReader sr = new StreamReader(Path.Combine(localPath, path))) { // Read the stream to a string, and write the string to the console. CSVstring = sr.ReadToEnd(); } } catch (IOException e) { Trainworks.Log(LogLevel.Error, "We couldn't read the file at " + Path.Combine(localPath, path)); Trainworks.Log(LogLevel.Error, e.Message); } List <string> categories = LocalizationManager.Sources[0].GetCategories(true, (List <string>)null); foreach (string Category in categories) { LocalizationManager.Sources[0].Import_CSV(Category, CSVstring, eSpreadsheetUpdateMode.AddNewTerms, Separator); } }
/// <summary> /// Builds the CardData represented by this builder's parameters recursively /// and registers it and its components with the appropriate managers. /// </summary> /// <returns>The newly registered CardData</returns> public CardData BuildAndRegister(int ChampionIndex = 0) { var cardData = this.Build(); Trainworks.Log(LogLevel.Debug, "Adding custom card: " + cardData.GetName()); CustomCardManager.RegisterCustomCard(cardData, this.CardPoolIDs); var Clan = cardData.GetLinkedClass(); ChampionData ClanChamp = Clan.GetChampionData(ChampionIndex); ClanChamp.championCardData = cardData; if (this.ChampionIconPath != null) { Sprite championIconSprite = CustomAssetManager.LoadSpriteFromPath(this.BaseAssetPath + "/" + this.ChampionIconPath); ClanChamp.championIcon = championIconSprite; } ClanChamp.starterCardData = StarterCardData; if (this.UpgradeTree != null) { ClanChamp.upgradeTree = UpgradeTree.Build(); } ClanChamp.championSelectedCue = ChampionSelectedCue; return(cardData); }
public GameObject Construct(AssetReference assetRef, BundleAssetLoadingInfo bundleInfo) { var asset = BundleManager.LoadAssetFromBundle(bundleInfo, bundleInfo.SpriteName); if (asset.GetType() == typeof(Texture2D)) { // "Type checking ew" // You're thinking it, I can tell. // Through all the horrible things we've done with this project, // type checking is where you draw the line? var tex = asset as Texture2D; if (tex != null) { Sprite sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f), 128f); return(CreateCardGameObject(assetRef, sprite)); } return(null); } else { var gameObject = asset as GameObject; if (gameObject != null) { GameObject.DontDestroyOnLoad(gameObject); return(gameObject); } } Trainworks.Log(BepInEx.Logging.LogLevel.Warning, "Invalid asset type " + asset.GetType() + " when loading asset: " + bundleInfo.SpriteName); return(null); }
public static string GenerateDeterministicGUID(string key) { if (key == null) { Trainworks.Log(BepInEx.Logging.LogLevel.Warning, "GUIDGenerator cannot generate determinstic GUID for null key"); return(key); } //Generate a byte array from a string using default encoding byte[] inputBytes = Encoding.Default.GetBytes(key); //Use bytes to generate a byte array of length 16 using MD5CryptoServiceProvider byte[] hashBytes = provider.ComputeHash(inputBytes); //Set the first nibble of the byte to be 0100 hashBytes[7] = (byte)(0x40 | ((int)hashBytes[7] & 0xf)); //Set the first crumb of the byte to be 10 hashBytes[8] = (byte)(0x80 | ((int)hashBytes[8] & 0x3f)); //Resize the array to get the first 16 bytes Array.Resize <byte>(ref hashBytes, 16); Guid guid = new Guid(hashBytes); return(guid.ToString()); }
private static void TemplateCharacterLoadingComplete(IAsyncOperation <GameObject> asyncOperation) { TemplateCharacter = asyncOperation.Result; if (TemplateCharacter == null) { Trainworks.Log(LogLevel.Warning, "Failed to load character template"); } }
public static Sprite LoadSpriteFromRuntimeKey(Hash128 runtimeKey) { if (RuntimeKeyToAssetInfo.ContainsKey(runtimeKey)) { return(LoadSpriteFromPath(RuntimeKeyToAssetInfo[runtimeKey].FullPath)); } Trainworks.Log(BepInEx.Logging.LogLevel.Warning, "Custom asset failed to load from runtime key: " + runtimeKey); return(null); }
/// <summary> /// /// </summary> /// <param name="cardPoolID"></param> /// <returns></returns> public static CardPool GetCustomCardPoolByID(string cardPoolID) { if (CustomCardPools.ContainsKey(cardPoolID)) { return(CustomCardPools[cardPoolID]); } Trainworks.Log(LogLevel.Warning, "Could not find card pool: " + cardPoolID); return(null); }
/// <summary> /// Builds the CardData represented by this builder's parameters recursively /// and registers it and its components with the appropriate managers. /// </summary> /// <returns>The newly registered CardData</returns> public CardData BuildAndRegister() { var cardData = this.Build(); Trainworks.Log(LogLevel.Debug, "Adding custom card: " + cardData.GetName()); CustomCardManager.RegisterCustomCard(cardData, this.CardPoolIDs); return(cardData); }
public static void RegisterCustomCardPool(CardPool cardPool) { if (!CustomCardPools.ContainsKey(cardPool.name)) { CustomCardPools.Add(cardPool.name, cardPool); } else { Trainworks.Log(LogLevel.Warning, "Attempted to register duplicate card pool with name: " + cardPool.name); } }
static void Postfix(ref CombatManager __instance) { Queue <CombatManager.TriggerQueueData> triggerQueue = (Queue <CombatManager.TriggerQueueData>)AccessTools.PropertyGetter(typeof(CombatManager), "TriggerQueue").Invoke(__instance, null); if (!__instance.IsRunningTriggerQueue) { foreach (CombatManager.TriggerQueueData data in triggerQueue.ToList()) { Trainworks.Log(BepInEx.Logging.LogLevel.Error, $"Trigger Not Enqued, will be cleared: {data.trigger}"); } } }
/// <summary> /// Register a custom card with the manager, allowing it to show up in game /// both in the logbook and whenever cards are chosen from the specified pools. /// </summary> /// <param name="cardData">The custom card data to register</param> /// <param name="cardPoolData">The card pools the custom card should be a part of</param> public static void RegisterCustomCard(CardData cardData, List <string> cardPoolData) { if (!CustomCardData.ContainsKey(cardData.GetID())) { CustomCardData.Add(cardData.GetID(), cardData); CustomCardPoolManager.AddCardToPools(cardData, cardPoolData); ProviderManager.SaveManager.GetAllGameData().GetAllCardData().Add(cardData); } else { Trainworks.Log(LogLevel.Warning, "Attempted to register duplicate card data with name: " + cardData.name); } }
/// <summary> /// Register a custom relic with the manager, allowing it to show up in game. /// </summary> /// <param name="relicData">The custom relic data to register</param> /// <param name="relicPoolData">The pools to insert the custom relic data into</param> public static void RegisterCustomRelic(CollectableRelicData relicData, List <string> relicPoolData) { if (!CustomRelicData.ContainsKey(relicData.GetID())) { CustomRelicData.Add(relicData.GetID(), relicData); CustomRelicPoolManager.AddRelicToPools(relicData, relicPoolData); ProviderManager.SaveManager.GetAllGameData().GetAllCollectableRelicData().Add(relicData); } else { Trainworks.Log(LogLevel.Warning, "Attempted to register duplicate relic data with name: " + relicData.name); } }
/// <summary> /// Register a custom class with the manager, allowing it to show up in game. /// </summary> /// <param name="classData">The custom class data to register</param> public static void RegisterCustomClass(ClassData classData) { if (!CustomClassData.ContainsKey(classData.GetID())) { CustomClassData.Add(classData.GetID(), classData); ProviderManager.SaveManager.GetAllGameData().GetAllClassDatas().Add(classData); ProviderManager.SaveManager.GetAllGameData().GetBalanceData().GetClassDatas().Add(classData); } else { Trainworks.Log(LogLevel.Warning, "Attempted to register duplicate class data with name: " + classData.name); } }
/// <summary> /// Register a custom character with the manager, allowing it to show up in game. /// </summary> /// <param name="data">The custom character data to register</param> public static bool RegisterCustomCharacter(CharacterData data) { if (!CustomCharacterData.ContainsKey(data.GetID())) { CustomCharacterData.Add(data.GetID(), data); ProviderManager.SaveManager.GetAllGameData().GetAllCharacterData().Add(data); return(true); } else { Trainworks.Log(LogLevel.Warning, "Attempted to register duplicate character data with name: " + data.name); return(false); } }
/// <summary> /// Create a sprite from texture at provided path. /// </summary> /// <param name="path">Absolute path of the texture</param> /// <returns>The sprite, or null if there is no texture at the given path</returns> public static Sprite LoadSpriteFromPath(string path) { if (File.Exists(path)) { // Create the card sprite byte[] fileData = File.ReadAllBytes(path); Texture2D tex = new Texture2D(1, 1); UnityEngine.ImageConversion.LoadImage(tex, fileData); Sprite sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f), 128f); sprite.name = Path.GetFileNameWithoutExtension(path); return(sprite); } Trainworks.Log(BepInEx.Logging.LogLevel.Warning, "No asset found at: " + path); return(null); }
/// <summary> /// Load an asset from an asset bundle /// </summary> /// <param name="info">Loading info for the asset</param> /// <param name="assetName">Name of the asset to load from the bundle</param> /// <returns>The asset specified by the given info as a UnityEngine object</returns> public static UnityEngine.Object LoadAssetFromBundle(BundleAssetLoadingInfo info, string assetName) { if (LoadedAssetBundles.ContainsKey(info.FullPath)) { var asset = LoadedAssetBundles[info.FullPath].LoadAsset(assetName); if (asset == null) { Trainworks.Log(BepInEx.Logging.LogLevel.Warning, "Custom asset: " + assetName + " failed to load from bundle: " + info.FullPath); } ApplyImportSettings(info, ref asset); return(asset); } Trainworks.Log(BepInEx.Logging.LogLevel.Warning, "Attempting to load asset from non-existent bundle: " + info.FullPath); return(null); }
/// <summary> /// A general function used to Apply a Card Trigger in different ways, dependant on parameters /// </summary> /// <param name="cardTrigger">CardTrigger to be Applied</param> /// <param name="playedCard">Card to apply triggers to</param> /// <param name="fireAllMonsterTriggersInRoom">Whether Apply Card Triggers should fire on monster's Instead, requires Trigger to have an associated character trigger</param> /// <param name="roomIndex">Room to fire triggers in, -1 defaults to selected room</param> /// <param name="ignoreDeadInTargeting">Whether effects applied by the trigger should ignore dead in targetting</param> /// <param name="triggeredCharacter">Character used to determine how many times Card Trigger should be applied</param> /// <param name="cardTriggerFiredCallback">Action to take after applying trigger</param> /// <returns></returns> public static void ApplyCardTriggers(CardTrigger cardTrigger, CardState playedCard, bool fireAllMonsterTriggersInRoom = false, int roomIndex = -1, bool ignoreDeadInTargeting = true, CharacterState triggeredCharacter = null, Action cardTriggerFiredCallback = null) { Trainworks.Log(BepInEx.Logging.LogLevel.Info, $"Applying {cardTrigger.Name}"); if (ProviderManager.TryGetProvider <CombatManager>(out CombatManager combatManager)) { combatManager.StartCoroutine( combatManager.ApplyCardTriggers( cardTrigger.GetEnum(), playedCard, fireAllMonsterTriggersInRoom, roomIndex, ignoreDeadInTargeting, triggeredCharacter, cardTriggerFiredCallback ) ); } }
/// <summary> /// Get the card data corresponding to the given ID /// </summary> /// <param name="cardID">ID of the card to get</param> /// <returns>The card data for the given ID</returns> public static CardData GetCardDataByID(string cardID) { // Search for custom card matching ID var guid = GUIDGenerator.GenerateDeterministicGUID(cardID); if (CustomCardData.ContainsKey(guid)) { return(CustomCardData[guid]); } // No custom card found; search for vanilla card matching ID var vanillaCard = ProviderManager.SaveManager.GetAllGameData().FindCardData(cardID); if (vanillaCard == null) { Trainworks.Log(LogLevel.All, "Couldn't find card: " + cardID + " - This will cause crashes."); } return(vanillaCard); }
/// <summary> /// Get the relic data corresponding to the given ID /// </summary> /// <param name="relicID">ID of the relic to get</param> /// <returns>The relic data for the given ID</returns> public static CollectableRelicData GetRelicDataByID(string relicID) { // Search for custom relic matching ID var guid = GUIDGenerator.GenerateDeterministicGUID(relicID); if (CustomRelicData.ContainsKey(guid)) { return(CustomRelicData[guid]); } // No custom relic found; search for vanilla relic matching ID var vanillaRelic = ProviderManager.SaveManager.GetAllGameData().FindCollectableRelicData(relicID); if (vanillaRelic == null) { Trainworks.Log(LogLevel.All, "Couldn't find relic: " + relicID + " - This will cause crashes."); } return(vanillaRelic); }
/// <summary> /// Base Constructor for creating an Extended Enumerator /// </summary> /// <param name="Name">Name of new Enum Value</param> /// <param name="ID">ID of new Enum Value</param> public ExtendedEnum(string Name, int ID) { this.ID = ID; this.Name = Name; if (NameToExtendedEnumMap.ContainsKey(this.Name)) { Trainworks.Log(BepInEx.Logging.LogLevel.Warning, $"Name: {this.Name} Conflict in domain, {typeof(TExtendedEnum).Name}"); } if (IntToExtendedEnumMap.ContainsKey(this.ID)) { Trainworks.Log(BepInEx.Logging.LogLevel.Warning, $"ID#{this.ID} Conflict between {Name} and {IntToExtendedEnumMap[this.ID].Name} in domain, {typeof(TExtendedEnum).Name}"); } if (ReservedIDs.Contains(this.ID)) { Trainworks.Log(BepInEx.Logging.LogLevel.Warning, $"ID#{this.ID} is Reserved and can't be set for {Name}"); } NameToExtendedEnumMap[Name] = (TExtendedEnum)this; IntToExtendedEnumMap[ID] = (TExtendedEnum)this; }
public static void RegisterBundle(string assetGUID, BundleAssetLoadingInfo bundleInfo) { string path = bundleInfo.FullPath; if (!LoadedAssetBundles.ContainsKey(path)) { if (File.Exists(path)) { LoadedAssetBundles[path] = AssetBundle.LoadFromFile(path); } else { Trainworks.Log(BepInEx.Logging.LogLevel.Warning, "Custom asset bundle failed to load from path: " + path); } } var runtimeKey = Hash128.Parse(assetGUID); RuntimeKeyToBundleInfo[runtimeKey] = bundleInfo; }
public static GameObject LoadGameObjectFromAssetRef(AssetReference assetRef) { var runtimeKey = assetRef.RuntimeKey; if (BundleManager.RuntimeKeyToBundleInfo.ContainsKey(runtimeKey)) { var bundleInfo = BundleManager.RuntimeKeyToBundleInfo[runtimeKey]; var assetType = RuntimeKeyToAssetInfo[runtimeKey].AssetType; var assetConstructor = AssetTypeToAssetConstructor[assetType]; return(assetConstructor.Construct(assetRef, bundleInfo)); } else if (RuntimeKeyToAssetInfo.ContainsKey(runtimeKey)) { var assetType = RuntimeKeyToAssetInfo[runtimeKey].AssetType; var assetConstructor = AssetTypeToAssetConstructor[assetType]; return(assetConstructor.Construct(assetRef)); } Trainworks.Log(BepInEx.Logging.LogLevel.Warning, "Runtime key is not registered with CustomAssetManager: " + runtimeKey); return(null); }
/// <summary> /// Get the character data corresponding to the given ID /// </summary> /// <param name="characterID">ID of the character to get</param> /// <returns>The character data for the given ID</returns> public static CharacterData GetCharacterDataByID(string characterID) { // Search for custom character matching ID var guid = GUIDGenerator.GenerateDeterministicGUID(characterID); if (CustomCharacterData.ContainsKey(guid)) { return(CustomCharacterData[guid]); } // No custom card found; search for vanilla character matching ID var vanillaChar = ProviderManager.SaveManager.GetAllGameData().GetAllCharacterData().Find((chara) => { return(chara.GetID() == characterID); }); if (vanillaChar == null) { Trainworks.Log(LogLevel.All, "Couldn't find character: " + characterID + " - This will cause crashes."); } return(vanillaChar); }
public GameObject Construct(AssetReference assetRef, BundleAssetLoadingInfo bundleInfo) { // Don't recreate if (CharacterPrefabDictionary.ContainsKey(bundleInfo.SpriteName)) { return(CharacterPrefabDictionary[bundleInfo.SpriteName]); } if (CharacterPrefabDictionary.ContainsKey(bundleInfo.ObjectName)) { return(CharacterPrefabDictionary[bundleInfo.ObjectName]); } // Create a new one if one doesn't exist already var tex = BundleManager.LoadAssetFromBundle(bundleInfo, bundleInfo.SpriteName) as Texture2D; if (tex != null) { Sprite sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f), 128f); sprite.name = "Sprite_" + bundleInfo.SpriteName.Replace("assets/", "").Replace(".png", ""); if (bundleInfo.ObjectName != null) { GameObject gameObject = BundleManager.LoadAssetFromBundle(bundleInfo, bundleInfo.ObjectName) as GameObject; if (gameObject != null) { var spineObj = CreateCharacterGameObject(assetRef, sprite, gameObject); GameObject.DontDestroyOnLoad(spineObj); CharacterPrefabDictionary.Add(bundleInfo.ObjectName, spineObj); return(spineObj); } } var charObj = CreateCharacterGameObject(assetRef, sprite); GameObject.DontDestroyOnLoad(charObj); CharacterPrefabDictionary.Add(bundleInfo.SpriteName, charObj); return(charObj); } Trainworks.Log(BepInEx.Logging.LogLevel.Warning, "Invalid sprite name when loading asset: " + bundleInfo.SpriteName); return(null); }
/// <summary> /// Create a GameObject for the custom character with the AssetReference and Sprite /// </summary> /// <param name="assetRef">Reference containing the asset information</param> /// <param name="sprite">Sprite to create character with</param> /// <returns>The GameObject for the character</returns> private static GameObject CreateCharacterGameObject(AssetReference assetRef, Sprite sprite) { /* * // This code attempts to construct a Spine Object with no animations to match the imported PNG file. This gives us better outlining, draw order, and highlighting. * * GameObject skeletonData = new GameObject(); * skeletonData.name = sprite.name; * var s = skeletonData.AddComponent<SkeletonAnimation>(); * * // All we need is a complete and valid SkeletonDataAsset... does that include the atlas primarymaterial, atlas data, skeletonjson, state, and skeleton? * s.skeletonDataAsset = new SkeletonDataAsset(); * s.skeletonDataAsset.skeletonJSON = new TextAsset("{\"skeleton\":{\"spine\":\"3.6.0.7-beta\",\"width\":" + sprite.rect.width + ",\"height\":" + sprite.rect.height + ",\"fps\":24,\"hash\":\" \",\"name\":\"Armature\"},\"bones\":[{\"name\":\"root\"}],\"slots\":[{\"name\":\"Unit\",\"bone\":\"root\",\"attachment\":\"Unit\"}],\"skins\":{\"default\":{\"Unit\":{\"Unit\":{\"name\":\"Unit\",\"width\":" + sprite.rect.width + ",\"height\":" + sprite.rect.height + ",\"y\":" + sprite.rect.width + "}}}}}"); * s.skeletonDataAsset.atlasAssets.AddToArray<AtlasAssetBase>(new SpineAtlasAsset()); * s.skeletonDataAsset.atlasAssets[0]. */ /* * Trainworks.Log(BepInEx.Logging.LogLevel.All, "We're doing the code!"); * var skeletonData = TrainworksBundle.LoadAsset("assets/PNGTemplate.prefab") as GameObject; * * return CreateCharacterGameObject(assetRef, sprite, skeletonData); */ Trainworks.Log(BepInEx.Logging.LogLevel.All, "Character Template: " + CustomCharacterManager.TemplateCharacter); // Create a new character GameObject by cloning an existing, working character var characterGameObject = GameObject.Instantiate(CustomCharacterManager.TemplateCharacter); // Set aside its CharacterState and CharacterUI components for later use var characterState = characterGameObject.GetComponentInChildren <CharacterState>(); var characterUI = characterGameObject.GetComponentInChildren <CharacterUI>(); // Set the name, and hide the UI characterUI.HideDetails(); characterGameObject.name = "Character_" + sprite.name; // Make its MeshRenderer active; this is what enables the sprite we're about to attach to show up characterGameObject.GetComponentInChildren <MeshRenderer>(true).gameObject.SetActive(true); // Delete all the spine anims var spine = characterGameObject.GetComponentInChildren <ShinyShoe.CharacterUIMeshSpine>(true); foreach (Transform child in spine.transform) { GameObject.Destroy(child.gameObject); } spine.gameObject.SetActive(false); // Set states in the CharacterState and CharacterUI to the sprite to show it ingame Traverse.Create(characterState).Field <Sprite>("sprite").Value = sprite; characterUI.GetSpriteRenderer().sprite = sprite; // Set up the outline Sprite - well, seems like there will be problems here var outlineMesh = characterGameObject.GetComponentInChildren <CharacterUIOutlineMesh>(true); //Traverse.Create(outlineMesh).Field("outlineData").Field<Texture2D>("characterTexture").Value = sprite.texture; //Traverse.Create(outlineMesh).Field("outlineData").Field<Texture2D>("outlineTexture").Value = sprite.texture; Traverse.Create(outlineMesh).Field <CharacterOutlineData>("outlineData").Value = null; //CharacterOutlineData.Create(sprite.texture); //Traverse.Create(outlineMesh).Field("outlineData").Field<Texture2D>("outlineTexture").Value = sprite.texture; return(characterGameObject); }