protected ModPrefab_Craftable( string techTypeName, string friendlyName, string description, TechType template, TechType requiredAnalysis, TechGroup groupForPDA, TechCategory categoryForPDA, EquipmentType equipmentType, QuickSlotType quickSlotType, CraftData.BackgroundType backgroundType, Vector2int itemSize, ModPrefab_Fragment fragment ) : base(techTypeName, $"{techTypeName}.Prefab") { TechTypeName = techTypeName; FriendlyName = friendlyName; Description = description; PrefabTemplate = template; RequiredForUnlock = requiredAnalysis; GroupForPDA = groupForPDA; CategoryForPDA = categoryForPDA; TypeForEquipment = equipmentType; TypeForQuickslot = quickSlotType; BackgroundType = backgroundType; ItemSize = itemSize; _Fragment = fragment; IngameMenuHandler.Main.RegisterOnQuitEvent(OnQuitEvent); }
private void PerformTakeOperation(TechType techType) { QuickLogger.Debug("Perform Take Operation", true); foreach (DSSRackController baseUnit in BaseRacks) { if (baseUnit.HasItem(techType)) { var data = baseUnit.GetItemDataFromServer(techType); QuickLogger.Debug("Calling Take", true); var result = baseUnit.GivePlayerItem(techType, data); if (!result) { return; //TODO Add Message } return; } } //Check connectables foreach (KeyValuePair <string, FCSConnectableDevice> fcsConnectable in FCSConnectables) { Vector2int itemSize = CraftData.GetItemSize(techType); if (fcsConnectable.Value.ContainsItem(techType) && Inventory.main.HasRoomFor(itemSize.x, itemSize.y)) { var item = fcsConnectable.Value.RemoveItemFromContainer(techType, 1); if (item == null) { continue; } DSSHelpers.GivePlayerItem(item); break; } } }
/// <summary> /// Get a <see cref="Vector2int"/> value using <see cref="PlayerPrefs"/> /// </summary> /// <param name="key"></param> /// <param name="defaultValue"></param> /// <returns></returns> public static Vector2int GetVector2int(string key, Vector2int defaultValue) { int x = PlayerPrefs.GetInt($"{key}_vector2int_x", defaultValue.x); int y = PlayerPrefs.GetInt($"{key}_vector2int_y", defaultValue.y); return(new Vector2int(x, y)); }
public static bool TryOverflowIntoBioreactors(SubRoot subRoot, TechType fishType, ref int breedCount) { BaseBioReactor[] bioReactors = subRoot?.gameObject?.GetComponentsInChildren <BaseBioReactor>() ?? new BaseBioReactor[0]; if (bioReactors.Length == 0) { return(breedCount > 0); } Vector2int sizePerFish = CraftData.GetItemSize(fishType); int failCount = 0; while (failCount < bioReactors.Length && breedCount > 0) { foreach (BaseBioReactor reactor in bioReactors) { if (breedCount > 0 && reactor.container.HasRoomFor(sizePerFish.x, sizePerFish.y)) { CoroutineHost.StartCoroutine(AddToReactor(subRoot, fishType, sizePerFish, reactor)); breedCount--; } else { failCount++; } } if (failCount < bioReactors.Length) { failCount = 0; } } return(breedCount > 0); }
protected Craftable( string nameID, string nameUsingForFiles, string friendlyName, string description, TechType template, CraftTree.Type fabricatorType, string fabricatorTab, TechType requiredAnalysis, TechGroup groupForPDA, TechCategory categoryForPDA, EquipmentType equipmentType, QuickSlotType quickSlotType, Vector2int itemSize, string gamerResourceFileName ) : base(nameID, $"{nameID}Prefab") { NameID = nameID; NameUsingForFiles = nameUsingForFiles; FriendlyName = friendlyName; Description = description; PrefabTemplate = template; FabricatorType = fabricatorType; FabricatorTab = fabricatorTab; RequiredForUnlock = requiredAnalysis; GroupForPDA = groupForPDA; CategoryForPDA = categoryForPDA; TypeForEquipment = equipmentType; TypeForQuickslot = quickSlotType; ItemSize = itemSize; GameResourceFileName = gamerResourceFileName; }
public static void OnMiddleClick(InventoryItem item) { Vector2int cursorPosition = GetCursorPosition(); DontEnable = true; Player.main.GetPDA().Close(); DontEnable = false; StorageContainer container = item.item.gameObject.GetComponentInChildren <PickupableStorage>().storageContainer; container.Open(); container.onUse.Invoke(); if (PlayerInventoryContains(item)) { if (LastOpened != null) { LastOpened.isEnabled = true; GetIconForItem(LastOpened)?.SetChroma(1f); } item.isEnabled = false; GetIconForItem(item)?.SetChroma(0f); LastOpened = item; } GameObject.FindObjectOfType <GameInput>().StartCoroutine(ResetCursor(cursorPosition)); }
public static bool TryOverflowIntoCyclopsBioreactors(SubRoot subRoot, TechType fishType, ref int breedCount) { CyBioReactorMono[] cyBioReactors = subRoot.GetComponentsInChildren <CyBioReactorMono>() ?? new CyBioReactorMono[0]; if (cyBioReactors.Length == 0) { return(breedCount > 0); } Vector2int sizePerFish = CraftData.GetItemSize(fishType); int failCount = 0; while (failCount < cyBioReactors.Length && breedCount > 0) { foreach (CyBioReactorMono reactor in cyBioReactors) { if (breedCount > 0 && reactor.container.HasRoomFor(sizePerFish.x, sizePerFish.y)) { CoroutineHost.StartCoroutine(AddToReactor(subRoot, fishType, sizePerFish, reactor)); breedCount--; } else { failCount++; } } if (failCount < cyBioReactors.Length) { failCount = 0; } } return(breedCount > 0); }
public static IEnumerator ResetCursor(Vector2int position) { yield return(new WaitForEndOfFrame()); yield return(new WaitForEndOfFrame()); SetCursorPosition(position); }
internal void CacheNewHasRoomData(ItemsContainer container, Vector2int itemSize, bool hasRoom) { HasRoomCacheCollection[container][itemSize] = hasRoom; // If item fits and is larger than 1x1, cache common sizes as true if (hasRoom && (itemSize.x > 1 || itemSize.y > 1)) { foreach (Vector2int size in CommonSmallerSizes(itemSize)) { HasRoomCacheCollection[container][size] = true; } } }
public static bool testContainer(ItemsContainer container) { List <TechType> techTypes = container.GetItemTypes(); if (techTypes.Count() == 1) { Vector2int itemSize = CraftData.GetItemSize(techTypes[0]); if (itemSize.x == 1 && itemSize.y == 1 && container.count <= (container.sizeX * container.sizeY * DW_Tweaks_Settings.Instance.ContainerOverstuff)) { return(true); } } return(false); }
private static void Postfix(FiltrationMachine __instance) { int maxSalt = Main.config.FiltrationSalt; int maxWater = Main.config.FiltrationWater; Vector2int newContainerSize = new Vector2int(Main.config.FiltrationWidth, Main.config.FiltrationHeight); #if !RELEASE Logger.Log(Logger.Level.Debug, $"Reconfiguring Filtration Machine {__instance.gameObject.name} with configuration values of: maxSalt {maxSalt}, maxWater {maxWater}, new size ({newContainerSize.x}, {newContainerSize.y})"); #endif __instance.maxSalt = maxSalt; __instance.maxWater = maxWater; __instance.storageContainer.Resize(newContainerSize.x, newContainerSize.y); }
/// <summary> /// Using the cached container info, determines whether the specified container has room for an item of the specified size. /// </summary> /// <param name="container">The container to check.</param> /// <param name="itemSize">Size of the item.</param> /// <returns> /// <c>true</c> if there is room for the item in the container,; otherwise, <c>false</c>. /// </returns> bool IStorageHelper.HasRoomForCached(ItemsContainer container, Vector2int itemSize) { if (HasRoomCacheCollection.TryGetValue(container, out Dictionary <Vector2int, bool> cache) && cache.TryGetValue(itemSize, out bool hasRoom)) { // Return the cached result return(hasRoom); } else { // Return the normal result, it will be cached for next time return(container.HasRoomFor(itemSize.x, itemSize.y)); } }
public static bool Prefix(ItemsContainer __instance, Pickupable pickupable, ref bool __result) { Vector2int itemSize = CraftData.GetItemSize(pickupable.GetTechType()); if (itemSize.x == 1 && itemSize.y == 1) { List <TechType> techTypes = __instance.GetItemTypes(); if (techTypes.Count() == 1 && techTypes[0] == pickupable.GetTechType() && __instance.count < (__instance.sizeX * __instance.sizeY * DW_Tweaks_Settings.Instance.ContainerOverstuff)) { __result = true; return(false); } } return(true); }
private static bool HasRoomFor_XY_Prefix(ItemsContainer __instance, int width, int height, ref bool __result, ref Vector2int __state) { // Completely avoid non-natural sizes due to game-breaking bugs if (width <= 0 || height <= 0) { __result = false; return(false); } __state = new Vector2int(width, height); // Internal Harmony parameter which is passed to the Postfix // If no result exists (false), return true and continue with code execution // If a result exists (true), detour the method and return the cached result return(!ItemStorageHelper.Singleton.TryGetCachedHasRoom(__instance, __state, ref __result)); }
public static IEnumerator AddToReactor(SubRoot subRoot, TechType fishType, Vector2int sizePerFish, BaseBioReactor reactor) { CoroutineTask <GameObject> task = CraftData.GetPrefabForTechTypeAsync(fishType, false); yield return(task); GameObject prefab = task.GetResult(); prefab.SetActive(false); if (!reactor.container.HasRoomFor(sizePerFish.x, sizePerFish.y)) { int breedCount = 1; if (QModServices.Main.ModPresent("FCSEnergySolutions")) { AGCompat.TryOverflowIntoAlterraGens(subRoot, fishType, ref breedCount); } if (QModServices.Main.ModPresent("CyclopsBioReactor") && breedCount > 0) { CBRCompat.TryOverflowIntoCyclopsBioreactors(subRoot, fishType, ref breedCount); } if (breedCount > 0) { Main.TryOverflowIntoBioreactors(subRoot, fishType, ref breedCount); } yield break; } GameObject gameObject = GameObject.Instantiate(prefab); Pickupable pickupable = gameObject.EnsureComponent <Pickupable>(); #if SUBNAUTICA_EXP TaskResult <Pickupable> taskResult = new TaskResult <Pickupable>(); yield return(pickupable.PickupAsync(taskResult, false)); pickupable = taskResult.Get(); #else pickupable.Pickup(false); #endif reactor.container.AddItem(pickupable); yield break; }
public void Patch_WhenSizeDifferent_CallsSetItemSize() { // ARRANGE const TechType createdTechType = TechType.Accumulator; _mockTechTypeHandler.AddTechType(Arg.Any <string>(), Arg.Any <string>(), Arg.Any <string>(), Arg.Any <string>(), Arg.Any <bool>()) .Returns(createdTechType); var customSize = new Vector2int(2, 2); _spawnable.DifferentSize = customSize; _spawnable.Patch(); Assert.AreEqual(createdTechType, _spawnable.TechType); _craftDataHandler.Received(1).SetItemSize(createdTechType, customSize); Assert.IsTrue(_spawnable.IsPatched); }
protected ModPrefab_Craftable( string nameID, string iconFilePath, TechType iconTechType, string friendlyName, string description, TechType template, TabNode newTabNode, CraftTree.Type[] fabricatorTypes, string[][] fabricatorTabs, TechType requiredAnalysis, TechGroup groupForPDA, TechCategory categoryForPDA, EquipmentType equipmentType, QuickSlotType quickSlotType, CraftData.BackgroundType backgroundType, Vector2int itemSize, string gamerResourceFileName, ModPrefab_Fragment fragment ) : base(nameID, $"{nameID}:Prefab") { NameID = nameID; IconFilePath = iconFilePath; IconTechType = iconTechType; FriendlyName = friendlyName; Description = description; PrefabTemplate = template; NewTabNode = newTabNode; FabricatorTypes = fabricatorTypes; FabricatorTabs = fabricatorTabs; RequiredForUnlock = requiredAnalysis; GroupForPDA = groupForPDA; CategoryForPDA = categoryForPDA; TypeForEquipment = equipmentType; TypeForQuickslot = quickSlotType; BackgroundType = backgroundType; ItemSize = itemSize; GameResourceFileName = gamerResourceFileName; _Fragment = fragment; //IngameMenuHandler.Main.RegisterOnQuitEvent(OnQuitEvent); }
// Called by ItemsContainer.HasRoom via Harmony internal bool TryGetCachedHasRoom(ItemsContainer container, Vector2int itemSize, ref bool cachedResult) { if (HasRoomCacheCollection.TryGetValue(container, out Dictionary <Vector2int, bool> cache)) { if (cache.TryGetValue(itemSize, out cachedResult)) { return(true); } // If no value is cached, the vanilla method will assign one } else { // This is a new container we haven't seen before, save it to the cache collection HasRoomCacheCollection.Add(container, new Dictionary <Vector2int, bool>()); } return(false); }
private IEnumerable <Vector2int> CommonSmallerSizes(Vector2int original) { if (original.x == 2) { if (original.y == 2) { return(SmallerThan2x2); } if (original.y > 2) { return(SmallerThan2x3); } } if (original.x >= 3 && original.y >= 3) { return(SmallerThan3x3); } return(Just1x1); }
public static void OnMiddleClick(InventoryItem item) { try { if (!PFC_Config.Enable) { ErrorMessage.AddMessage($"[{QMod.assembly}] Mod is disabled!"); return; } Vector2int cursorPosition = GetCursorPosition(); DontEnable = true; Player.main.GetPDA().Close(); DontEnable = false; StorageContainer container = item.item.gameObject.GetComponentInChildren <PickupableStorage>().storageContainer; container.Open(); container.onUse.Invoke(); if (PlayerInventoryContains(item)) { if (LastOpened != null) { LastOpened.isEnabled = true; GetIconForItem(LastOpened)?.SetChroma(1f); } item.isEnabled = false; GetIconForItem(item)?.SetChroma(0f); LastOpened = item; } GameObject.FindObjectOfType <GameInput>().StartCoroutine(ResetCursor(cursorPosition)); } catch (Exception e) { Logger.Exception(e); } }
private static void BreakIntoResources_Patch(BreakableResource __instance) { __instance.SendMessage("OnBreakResource", null, SendMessageOptions.DontRequireReceiver); if (__instance.gameObject.GetComponent <VFXBurstModel>()) { __instance.gameObject.BroadcastMessage("OnKill"); } else { UnityEngine.Object.Destroy(__instance.gameObject); } if (__instance.customGoalText != "") { GoalManager.main.OnCustomGoalEvent(__instance.customGoalText); } bool flag = false; for (int i = 0; i < __instance.numChances; i++) { GameObject gameObject = __instance.ChooseRandomResource(); if (gameObject) { QModManager.Utility.Logger.Log(QModManager.Utility.Logger.Level.Debug, "1 - Random Resouce is called"); if (Player.main.GetVehicle() is Exosuit exosuit) { QModManager.Utility.Logger.Log(QModManager.Utility.Logger.Level.Debug, "2 - Start AddToPrawn over randomress"); AddtoPrawn(__instance, exosuit, gameObject); } else { if ((Inventory.main.equipment.GetTechTypeInSlot("Gloves") == MetalHands.MetalHandsMK2TechType) | (MetalHands.Config.Config_fastcollect == true)) { QModManager.Utility.Logger.Log(QModManager.Utility.Logger.Level.Debug, "3 - Player has glove - randomress"); Vector2int size = CraftData.GetItemSize(CraftData.GetTechType(gameObject)); Inventory inventory = Inventory.Get(); if (inventory.HasRoomFor(size.x, size.y)) { CraftData.AddToInventory(CraftData.GetTechType(gameObject)); } else { __instance.SpawnResourceFromPrefab(gameObject); } } else { __instance.SpawnResourceFromPrefab(gameObject); } } flag = true; } } if (!flag) { QModManager.Utility.Logger.Log(QModManager.Utility.Logger.Level.Debug, "5 - default resouce is called"); if (Player.main.GetVehicle() is Exosuit exosuit) { QModManager.Utility.Logger.Log(QModManager.Utility.Logger.Level.Debug, "6 - Start AddToPrawn over defaultress"); AddtoPrawn(__instance, exosuit, __instance.defaultPrefab); } else if ((Inventory.main.equipment.GetTechTypeInSlot("Gloves") == MetalHands.MetalHandsMK2TechType) | (MetalHands.Config.Config_fastcollect == true)) { QModManager.Utility.Logger.Log(QModManager.Utility.Logger.Level.Debug, "7 - Player has glove - defaultress"); Vector2int size = CraftData.GetItemSize(CraftData.GetTechType(__instance.defaultPrefab)); Inventory inventory = Inventory.Get(); if (inventory.HasRoomFor(size.x, size.y)) { CraftData.AddToInventory(CraftData.GetTechType(__instance.defaultPrefab)); } else { __instance.SpawnResourceFromPrefab(__instance.defaultPrefab); } } else { __instance.SpawnResourceFromPrefab(__instance.defaultPrefab); } } FMODUWE.PlayOneShot(__instance.breakSound, __instance.transform.position, 1f); if (__instance.hitFX) { Utils.PlayOneShotPS(__instance.breakFX, __instance.transform.position, Quaternion.Euler(new Vector3(270f, 0f, 0f)), null); } QModManager.Utility.Logger.Log(QModManager.Utility.Logger.Level.Debug, "9 - Original Methode ending"); }
/// <summary> /// <para>Allows you to edit item sizes for TechTypes.</para> /// <para>Can be used for existing TechTypes too.</para> /// </summary> /// <param name="techType">The TechType whose item size you want to edit.</param> /// <param name="size">The item size for that TechType.</param> public static void SetItemSize(TechType techType, Vector2int size) { Main.SetItemSize(techType, size); }
/// <summary> /// Using the cached container info, determines whether the specified container has room for an item of the specified size. /// </summary> /// <param name="container">The container to check.</param> /// <param name="itemSize">Size of the item.</param> /// <returns> /// <c>true</c> if there is room for the item in the container,; otherwise, <c>false</c>. /// </returns> public static bool HasRoomCached(ItemsContainer container, Vector2int itemSize) { return(Main.HasRoomForCached(container, itemSize)); }
public static bool Prefix(Constructable __instance) { #endif if (Player.main.GetVehicle() != null && GameModeUtils.RequiresIngredients()) { Vehicle thisVehicle = Player.main.GetVehicle(); if (__instance._constructed) { return(true); } int count = __instance.resourceMap.Count; int resourceID = __instance.GetResourceID(); float backupConstructedAmount = __instance.constructedAmount; __instance.constructedAmount -= Time.deltaTime / (count * Constructable.GetConstructInterval()); __instance.constructedAmount = Mathf.Clamp01(__instance.constructedAmount); int resourceID2 = __instance.GetResourceID(); if (resourceID2 != resourceID) { TechType techType = __instance.resourceMap[resourceID2]; Vector2int size = #if SN1 CraftData.GetItemSize(techType); #elif BZ TechData.GetItemSize(techType); #endif if (thisVehicle.GetType().Equals(typeof(Exosuit))) { StorageContainer storageContainer = ((Exosuit)thisVehicle).storageContainer; if (storageContainer.container.HasRoomFor(size.x, size.y)) { CoroutineHost.StartCoroutine(AddToVehicle(techType, storageContainer.container)); } else { __instance.constructedAmount = backupConstructedAmount; return(true); } } #if SN1 else { SeaMoth seamoth = (SeaMoth)thisVehicle; bool storageCheck = false; for (int i = 0; i < 12; i++) { try { ItemsContainer storage = seamoth.GetStorageInSlot(i, TechType.VehicleStorageModule); if (storage != null && storage.HasRoomFor(size.x, size.y)) { CoroutineHost.StartCoroutine(AddToVehicle(techType, storage)); storageCheck = true; break; } } catch (Exception) { continue; } } if (!storageCheck) { __instance.constructedAmount = backupConstructedAmount; return(true); } } #endif } __instance.UpdateMaterial(); #if SUBNAUTICA_EXP || BZ result.Set(__instance.constructedAmount <= 0f); return(false); #elif SUBNAUTICA_STABLE return(__instance.constructedAmount <= 0f); #endif } return(true); }
public static void SetCursorPosition(Vector2int position) { SetCursorPos(position.x, position.y); }
private static void HasRoomFor_Postfix(ItemsContainer __instance, bool __result, Vector2int __state) { // We should only enter this method if the Prefix didn't have a cached value to use // Catch the result and map it to the size provided by the Prefix ItemStorageHelper.Singleton.CacheNewHasRoomData(__instance, __state, __result); }
public static void Postfix(ref Vector2int __result) { __result = new Vector2int(1, 1); }
public bool TryGetModSize(string Identifier, out Vector2int newSize) { string lowID = Identifier.ToLower(); Vector2int defaultSize; bool bHasDefault = defaultStorageSizes.TryGetValue(Identifier, out defaultSize); if (bHasDefault) { #if !RELEASE Logger.Log(Logger.Level.Debug, $"Found default values for ID {Identifier} using TryGetValue"); #endif } else { // Go through the defaults list manually; this *shouldn't* be necessary, as the dictionary has been declared with the IgnoreCase comparer, but // experience has not borne this out. foreach (KeyValuePair <string, Vector2int> kvp in defaultStorageSizes) { string key = kvp.Key.ToLower(); if (key == lowID) { bHasDefault = true; defaultSize = kvp.Value; #if !RELEASE Logger.Log(Logger.Level.Debug, $"Found default values for ID {Identifier} on manual review that were not found with TryGetValue"); #endif break; } } } newSize = new Vector2int(0, 0); if (StorageSizes.TryGetValue(Identifier, out newSize)) { #if !RELEASE Logger.Log(Logger.Level.Debug, $"Found configured values for ID {Identifier} using TryGetValue"); #endif if (bHasDefault) { // Return a value of true if the new value is different from default, and false if it's equal return(!(newSize.Equals(defaultSize))); } else { return(true); } } else { foreach (KeyValuePair <string, Vector2int> kvp in StorageSizes) { if (lowID == kvp.Key.ToLower()) { newSize = kvp.Value; #if !RELEASE Logger.Log(Logger.Level.Debug, $"Found configured values for ID {Identifier} on manual review that were not found with TryGetValue"); #endif if (bHasDefault) { return(!(newSize.Equals(defaultSize))); } else { return(true); } } } } // Couldn't find a value for this identifier, so: #if !RELEASE Logger.Log(Logger.Level.Debug, "Could not find " + (bHasDefault ? "" : "default or ") + "configured values for the identifier " + Identifier); #endif return(false); }
/// <summary> /// Set a <see cref="Vector2int"/> value using <see cref="PlayerPrefs"/> /// </summary> /// <param name="key"></param> /// <param name="value"></param> public static void SetVector2int(string key, Vector2int value) { PlayerPrefs.SetInt($"{key}_vector2int_x", value.x); PlayerPrefs.SetInt($"{key}_vector2int_y", value.y); }
/// <summary> /// Using the cached container info, determines whether the specified container has room for an item of the specified size. /// </summary> /// <param name="container">The container to check.</param> /// <param name="itemSize">Size of the item.</param> /// <returns> /// <c>true</c> if there is room for the item in the container,; otherwise, <c>false</c>. /// </returns> public static bool HasRoomCached(this ItemsContainer container, Vector2int itemSize) { return(ItemStorageHelper.Main.HasRoomForCached(container, itemSize)); }