/// <summary> /// Performs a delayed init on the sent list of sosigs. If a sosig fails to init, any character using that sosig will be removed /// </summary> /// <param name="sosigs"></param> private static void InitSosigs(List <SosigTemplate> sosigs) { for (int i = 0; i < sosigs.Count; i++) { SosigTemplate sosig = sosigs[i]; try { sosig.DelayedInit(); } catch (Exception e) { TNHTweakerLogger.LogError("TNHTweaker -- Failed to load sosig: " + sosig.DisplayName + ". Error Output:\n" + e.ToString()); //Find any characters that use this sosig, and remove them for (int j = 0; j < LoadedTemplateManager.LoadedCharactersDict.Values.Count; j++) { //This is probably monsterously inefficient, but if you're at this point you're already f****d :) KeyValuePair <TNH_CharacterDef, CustomCharacter> value_pair = LoadedTemplateManager.LoadedCharactersDict.ToList()[j]; if (value_pair.Value.CharacterUsesSosig(sosig.SosigEnemyID)) { TNHTweakerLogger.LogError("TNHTweaker -- Removing character that used removed sosig: " + value_pair.Value.DisplayName); LoadedTemplateManager.LoadedCharactersDict.Remove(value_pair.Key); j -= 1; } } } } }
public SosigEnemyTemplate GetSosigEnemyTemplate() { if (template == null) { TNHTweakerLogger.Log("TNHTweaker -- Getting sosig template", TNHTweakerLogger.LogType.Character); template = (SosigEnemyTemplate)ScriptableObject.CreateInstance(typeof(SosigEnemyTemplate)); template.DisplayName = DisplayName; template.SosigEnemyCategory = SosigEnemyCategory; template.SecondaryChance = SecondaryChance; template.TertiaryChance = TertiaryChance; TNHTweakerLogger.Log("TNHTweaker -- Getting sosig config", TNHTweakerLogger.LogType.Character); template.ConfigTemplates = new List <SosigConfigTemplate>(); foreach (SosigConfig temp in Configs) { if (temp == null) { TNHTweakerLogger.LogError("One of the sosig configs is null!"); continue; } template.ConfigTemplates.Add(temp.GetConfigTemplate()); } template.ConfigTemplates_Easy = ConfigsEasy.Select(o => o.GetConfigTemplate()).ToList(); template.OutfitConfig = OutfitConfigs.Select(o => o.GetOutfitConfig()).ToList(); } return(template); }
/// <summary> /// Takes a custom SosigTemplate object, and adds it to the necessary dictionaries. This method assumes that you are sending a template for a custom sosig, and that it should be given a new the SosigEnemyID /// </summary> /// <param name="template">A template for a custom sosig (Loaded at runtime)</param> public static void AddSosigTemplate(SosigTemplate template) { SosigEnemyTemplate realTemplate = template.GetSosigEnemyTemplate(); //Since this template is for a custom sosig, we should give it a brand new SosigEnemyID if (!SosigIDDict.ContainsKey(template.SosigEnemyID)) { SosigIDDict.Add(template.SosigEnemyID, NewSosigID); NewSosigID += 1; } else { TNHTweakerLogger.LogError("TNHTweaker -- Loaded sosig had same SosigEnemyID as another sosig -- SosigEnemyID : " + template.SosigEnemyID); return; } //Now fill out the SosigEnemyIDs values for the real sosig template (These will effectively be ints, but this is ok since enums are just ints in disguise) realTemplate.SosigEnemyID = (SosigEnemyID)SosigIDDict[template.SosigEnemyID]; //Finally add the templates to our global dictionary CustomSosigs.Add(template); LoadedSosigsDict.Add(realTemplate, template); TNHTweakerLogger.Log("TNHTweaker -- Sosig added successfuly : " + template.DisplayName, TNHTweakerLogger.LogType.Character); }
public void Awake() { original = gameObject.GetComponent <TNH_MagDuplicator>(); if (original == null) { TNHTweakerLogger.LogError("Fire Rate Modifier failed, original Mag Duplicator was null!"); } original.enabled = false; InitPanel(); UpdateIcons(); }
public void Awake() { original = gameObject.GetComponent <TNH_MagDuplicator>(); if (original == null) { TNHTweakerLogger.LogError("Mag Upgrader failed, original Mag Duplicator was null!"); } original.enabled = false; blacklist = LoadedTemplateManager.LoadedCharactersDict[original.M.C].GetMagazineBlacklist(); InitPanel(); UpdateIcons(); }
/// <summary> /// Performs a delayed init on the sent list of custom characters, and removes any characters that failed to init /// </summary> /// <param name="characters"></param> /// <param name="isCustom"></param> private static void InitCharacters(List <CustomCharacter> characters, bool isCustom) { for (int i = 0; i < characters.Count; i++) { CustomCharacter character = characters[i]; try { character.DelayedInit(isCustom); } catch (Exception e) { TNHTweakerLogger.LogError("TNHTweaker -- Failed to load character: " + character.DisplayName + ". Error Output:\n" + e.ToString()); characters.RemoveAt(i); LoadedTemplateManager.LoadedCharactersDict.Remove(character.GetCharacter()); i -= 1; } } }
public void LoadAsset(SetupStage stage, Mod mod, IHandle handle) { if (handle is not IFileHandle file) { throw new ArgumentException("Could not load sosig! Make sure you're pointing to a sosig template json file in the manifest"); } try { SosigTemplate sosig = stage.ImmediateReaders.Get <JToken>()(file).ToObject <SosigTemplate>(); TNHTweakerLogger.Log("TNHTweaker -- Sosig loaded successfuly : " + sosig.DisplayName, TNHTweakerLogger.LogType.File); LoadedTemplateManager.AddSosigTemplate(sosig); } catch (Exception e) { TNHTweakerLogger.LogError("Failed to load setup assets for sosig file! Caused Error: " + e.ToString()); } }
public void LoadAsset(SetupStage stage, Mod mod, IHandle handle) { if (handle is not IFileHandle file) { throw new ArgumentException("Could not load vault file! Make sure you're pointing to a vault json file in the manifest"); } try { SavedGunSerializable savedGun = stage.ImmediateReaders.Get <JToken>()(file).ToObject <SavedGunSerializable>(); TNHTweakerLogger.Log("TNHTweaker -- Vault file loaded successfuly : " + savedGun.FileName, TNHTweakerLogger.LogType.File); LoadedTemplateManager.AddVaultFile(savedGun); } catch (Exception e) { TNHTweakerLogger.LogError("Failed to load setup assets for vault file! Caused Error: " + e.ToString()); } }
public static void AddSosigTemplate(SosigEnemyTemplate realTemplate) { SosigTemplate template = new SosigTemplate(realTemplate); //This template is from a sogig that already has a valid SosigEnemyID, so we can just add that to the dictionary casted as an int if (!SosigIDDict.ContainsKey(template.SosigEnemyID)) { SosigIDDict.Add(template.SosigEnemyID, (int)realTemplate.SosigEnemyID); } else { TNHTweakerLogger.LogError("TNHTweaker -- Loaded sosig had same SosigEnemyID as another sosig -- SosigEnemyID : " + template.SosigEnemyID); return; } //Since the real template already had a valid SosigEnemyID, we can skip the part where we reassign them DefaultSosigs.Add(realTemplate); LoadedSosigsDict.Add(realTemplate, template); TNHTweakerLogger.Log("TNHTweaker -- Sosig added successfuly : " + template.DisplayName, TNHTweakerLogger.LogType.Character); }
public static IEnumerator SendScore(int score) { TNHTweakerLogger.Log("Sending modded score to the TNH Dashboard", TNHTweakerLogger.LogType.TNH); waitForScore = true; //First, send the map data for this map using (UnityWebRequest wwwSendMap = new UnityWebRequest("https://tnh-dashboard.azure-api.net/v1/api/maps", "Put")) { wwwSendMap.SetRequestHeader(Globals.Accept, "*/*"); wwwSendMap.SetRequestHeader(Globals.Content_Type, Globals.ApplicationJson); GetHoldList().ForEach(o => TNHTweakerLogger.Log($"Hold: x={o.x}, z={o.z}", TNHTweakerLogger.LogType.TNH)); MapData mapData = new MapData() { MapName = GM.TNH_Manager.LevelName, HoldPointLocations = JsonConvert.SerializeObject(GetHoldList()), SupplyPointLocations = JsonConvert.SerializeObject(GetSupplyList()) }; string data = JsonConvert.SerializeObject(mapData); wwwSendMap.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(data)); wwwSendMap.uploadHandler.contentType = "application/json"; yield return(wwwSendMap.Send()); if (wwwSendMap.isError) { TNHTweakerLogger.LogError("Something bad happened sending map data! \n" + wwwSendMap.error); } else { TNHTweakerLogger.Log("Sent map data", TNHTweakerLogger.LogType.TNH); } } //Now send the score using (UnityWebRequest wwwScores = new UnityWebRequest("https://tnh-dashboard.azure-api.net/v1/api/scores", "Put")) { wwwScores.SetRequestHeader(Globals.Accept, "*/*"); wwwScores.SetRequestHeader(Globals.Content_Type, Globals.ApplicationJson); ScoreEntry entry = GetScoreEntry(GM.TNH_Manager, score); string data = JsonConvert.SerializeObject(entry); wwwScores.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(data)); wwwScores.uploadHandler.contentType = "application/json"; yield return(wwwScores.Send()); if (wwwScores.isError) { TNHTweakerLogger.LogError("Something bad happened sending score! \n" + wwwScores.error); } else { TNHTweakerLogger.Log("Sent score data", TNHTweakerLogger.LogType.TNH); } } waitForScore = false; }
public static IEnumerator GetPlayerScores(int num_before, int num_after, TNH_ScoreDisplay instance) { TNHTweakerLogger.Log("Getting player scores from TNH Dashboard", TNHTweakerLogger.LogType.TNH); string url = "https://tnh-dashboard.azure-api.net/v1/api/scores/search"; List <RUST.Steamworks.HighScoreManager.HighScore> combinedScores = new List <RUST.Steamworks.HighScoreManager.HighScore>(); if (GM.TNH_Manager != null) { url += "?character=" + GM.TNH_Manager.C.DisplayName; url += "&map=" + GM.TNH_Manager.LevelName; url += "&health=" + health[(int)GM.TNHOptions.HealthModeSetting]; url += "&equipment=" + equipment[(int)GM.TNHOptions.EquipmentModeSetting]; url += "&length=" + length[(int)GM.TNHOptions.ProgressionTypeSetting]; url += "&name=" + SteamFriends.GetPersonaName(); url += "&num_before=1"; url += "&num_after=1"; } else { TNH_UIManager manager = GameObject.FindObjectOfType <TNH_UIManager>(); if (manager == null) { TNHTweakerLogger.LogError("Neither the TNH Manager or the UI Manager were found! Scores will not display"); yield break; } url += "?character=" + manager.CharDatabase.GetDef((TNH_Char)GM.TNHOptions.LastPlayedChar).DisplayName; url += "&map=" + manager.CurLevelID; url += "&health=" + health[(int)GM.TNHOptions.HealthModeSetting]; url += "&equipment=" + equipment[(int)GM.TNHOptions.EquipmentModeSetting]; url += "&length=" + length[(int)GM.TNHOptions.ProgressionTypeSetting]; url += "&name=" + SteamFriends.GetPersonaName(); url += "&num_before=1"; url += "&num_after=1"; } TNHTweakerLogger.Log("Request URL: " + url, TNHTweakerLogger.LogType.TNH); using (UnityWebRequest wwwGetScores = UnityWebRequest.Get(url)) { yield return(wwwGetScores.Send()); if (wwwGetScores.isError) { TNHTweakerLogger.LogError("Something bad happened getting scores \n" + wwwGetScores.error); } else if (wwwGetScores.responseCode == 404) { TNHTweakerLogger.LogWarning("High scores not found for player in table!"); combinedScores.AddRange(instance.m_scoresTop.Take(6)); } else { TNHTweakerLogger.Log("Got Scores!", TNHTweakerLogger.LogType.TNH); string scores = wwwGetScores.downloadHandler.text; TNHTweakerLogger.Log(scores, TNHTweakerLogger.LogType.TNH); List <ScoreEntry> playerScores = JsonConvert.DeserializeObject <List <ScoreEntry> >(scores); for (int i = 0; i < playerScores.Count; i++) { instance.m_scoresPlayer.Add(new RUST.Steamworks.HighScoreManager.HighScore() { name = playerScores[i].Name, rank = playerScores[i].Rank, score = playerScores[i].Score }); } if (instance.m_scoresTop != null) { combinedScores.AddRange(instance.m_scoresTop.Take(3)); } if (instance.m_scoresPlayer != null) { combinedScores.AddRange(instance.m_scoresPlayer.Take(3)); } } } instance.m_hasScoresPlayer = true; instance.SetGlobalHighScoreDisplay(combinedScores); }
public static Sosig SpawnEnemy(SosigTemplate template, CustomCharacter character, Vector3 spawnLocation, Quaternion spawnRotation, TNHModifier_AIDifficulty difficulty, int IFF, bool isAssault, Vector3 pointOfInterest, bool allowAllWeapons) { if (character.ForceAllAgentWeapons) { allowAllWeapons = true; } TNHTweakerLogger.Log("TNHTWEAKER -- Spawning sosig: " + template.SosigEnemyID, TNHTweakerLogger.LogType.TNH); //Create the sosig object GameObject sosigPrefab = UnityEngine.Object.Instantiate(IM.OD[template.SosigPrefabs.GetRandom <string>()].GetGameObject(), spawnLocation, spawnRotation); Sosig sosigComponent = sosigPrefab.GetComponentInChildren <Sosig>(); //Fill out the sosigs config based on the difficulty SosigConfig config; if (difficulty == TNHModifier_AIDifficulty.Arcade && template.ConfigsEasy.Count > 0) { config = template.ConfigsEasy.GetRandom <SosigConfig>(); } else if (template.Configs.Count > 0) { config = template.Configs.GetRandom <SosigConfig>(); } else { TNHTweakerLogger.LogError("TNHTweaker -- Sosig did not have normal difficulty config when playing on normal difficulty! Not spawning this enemy!"); return(null); } sosigComponent.Configure(config.GetConfigTemplate()); sosigComponent.SetIFF(IFF); //Setup the sosigs inventory sosigComponent.Inventory.Init(); sosigComponent.Inventory.FillAllAmmo(); sosigComponent.InitHands(); //Equip the sosigs weapons if (template.WeaponOptions.Count > 0) { GameObject weaponPrefab = IM.OD[template.WeaponOptions.GetRandom <string>()].GetGameObject(); EquipSosigWeapon(sosigComponent, weaponPrefab, difficulty); } if (template.WeaponOptionsSecondary.Count > 0 && allowAllWeapons && template.SecondaryChance >= UnityEngine.Random.value) { GameObject weaponPrefab = IM.OD[template.WeaponOptionsSecondary.GetRandom <string>()].GetGameObject(); EquipSosigWeapon(sosigComponent, weaponPrefab, difficulty); } if (template.WeaponOptionsTertiary.Count > 0 && allowAllWeapons && template.TertiaryChance >= UnityEngine.Random.value) { GameObject weaponPrefab = IM.OD[template.WeaponOptionsTertiary.GetRandom <string>()].GetGameObject(); EquipSosigWeapon(sosigComponent, weaponPrefab, difficulty); } //Equip clothing to the sosig OutfitConfig outfitConfig = template.OutfitConfigs.GetRandom <OutfitConfig>(); if (outfitConfig.Chance_Headwear >= UnityEngine.Random.value) { EquipSosigClothing(outfitConfig.Headwear, sosigComponent.Links[0], outfitConfig.ForceWearAllHead); } if (outfitConfig.Chance_Facewear >= UnityEngine.Random.value) { EquipSosigClothing(outfitConfig.Facewear, sosigComponent.Links[0], outfitConfig.ForceWearAllFace); } if (outfitConfig.Chance_Eyewear >= UnityEngine.Random.value) { EquipSosigClothing(outfitConfig.Eyewear, sosigComponent.Links[0], outfitConfig.ForceWearAllEye); } if (outfitConfig.Chance_Torsowear >= UnityEngine.Random.value) { EquipSosigClothing(outfitConfig.Torsowear, sosigComponent.Links[1], outfitConfig.ForceWearAllTorso); } if (outfitConfig.Chance_Pantswear >= UnityEngine.Random.value) { EquipSosigClothing(outfitConfig.Pantswear, sosigComponent.Links[2], outfitConfig.ForceWearAllPants); } if (outfitConfig.Chance_Pantswear_Lower >= UnityEngine.Random.value) { EquipSosigClothing(outfitConfig.Pantswear_Lower, sosigComponent.Links[3], outfitConfig.ForceWearAllPantsLower); } if (outfitConfig.Chance_Backpacks >= UnityEngine.Random.value) { EquipSosigClothing(outfitConfig.Backpacks, sosigComponent.Links[1], outfitConfig.ForceWearAllBackpacks); } //Setup the sosigs orders if (isAssault) { sosigComponent.CurrentOrder = Sosig.SosigOrder.Assault; sosigComponent.FallbackOrder = Sosig.SosigOrder.Assault; sosigComponent.CommandAssaultPoint(pointOfInterest); } else { sosigComponent.CurrentOrder = Sosig.SosigOrder.Wander; sosigComponent.FallbackOrder = Sosig.SosigOrder.Wander; sosigComponent.CommandGuardPoint(pointOfInterest, true); sosigComponent.SetDominantGuardDirection(UnityEngine.Random.onUnitSphere); } sosigComponent.SetGuardInvestigateDistanceThreshold(25f); //Handle sosig dropping custom loot if (UnityEngine.Random.value < template.DroppedLootChance && template.DroppedObjectPool != null) { SosigLinkLootWrapper component = sosigComponent.Links[2].gameObject.AddComponent <SosigLinkLootWrapper>(); component.shouldDropOnCleanup = !character.DisableCleanupSosigDrops; component.group = template.DroppedObjectPool; } return(sosigComponent); }
public void LoadAsset(SetupStage stage, Mod mod, IHandle handle) { if (handle is not IDirectoryHandle dir) { throw new ArgumentException("Could not load character! Character should point to a folder holding the character.json and thumb.png"); } try { CustomCharacter character = null; Sprite thumbnail = null; foreach (IFileHandle file in dir.GetFiles()) { if (file.Path.EndsWith("character.json")) { string charString = stage.ImmediateReaders.Get <string>()(file); JsonSerializerSettings settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; character = JsonConvert.DeserializeObject <CustomCharacter>(charString, settings); } else if (file.Path.EndsWith("thumb.png")) { thumbnail = TNHTweakerUtils.LoadSprite(file); } } if (character == null) { TNHTweakerLogger.LogError("TNHTweaker -- Failed to load custom character! No character.json file found"); return; } else if (thumbnail == null) { TNHTweakerLogger.LogError("TNHTweaker -- Failed to load custom character! No thumb.png file found"); return; } //Now we want to load the icons for each pool foreach (IFileHandle iconFile in dir.GetFiles()) { foreach (EquipmentPool pool in character.EquipmentPools) { if (iconFile.Path.EndsWith(pool.IconName)) { pool.GetPoolEntry().TableDef.Icon = TNHTweakerUtils.LoadSprite(iconFile); } } } TNHTweakerLogger.Log("TNHTweaker -- Character loaded successfuly : " + character.DisplayName, TNHTweakerLogger.LogType.File); LoadedTemplateManager.AddCharacterTemplate(character, thumbnail); } catch (Exception e) { TNHTweakerLogger.LogError("Failed to load setup assets for character! Caused Error: " + e.ToString()); } }