private static IEnumerator SpawnCreature(WaterPark waterPark, WaterParkCreature parkCreature, ItemsContainer container)
        {
            CoroutineTask <GameObject> task = CraftData.GetPrefabForTechTypeAsync(parkCreature.pickupable.GetTechType(), false);

            yield return(task);

            GameObject prefab = task.GetResult();

            prefab.SetActive(false);
            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
            container.AddItem(pickupable);

            yield break;
        }
Beispiel #2
0
        public static bool TryBreedIntoAlterraGen(WaterPark waterPark, TechType parkCreatureTechType, WaterParkCreature parkCreature)
        {
            var componentInParent = waterPark != null?waterPark.gameObject.GetComponentInParent <SubRoot>() : null;

            var AlterraGens = componentInParent != null
                ? componentInParent.gameObject.GetComponentsInChildren <IFCSStorage>()
                : null;

            if (AlterraGens is null)
            {
                return(false);
            }

            foreach (var storage in AlterraGens)
            {
                if (!storage.GetType().Name.Contains("AlterraGen") ||
                    !storage.IsAllowedToAdd(parkCreature.pickupable, false))
                {
                    continue;
                }

                CoroutineHost.StartCoroutine(AddItemToAlterraGen(parkCreatureTechType, storage));
                return(true);
            }

            return(false);
        }
Beispiel #3
0
        private void AssignToWaterPark(String waterParkGuid, Pickupable pickupable)
        {
            GameObject waterParkGo = GuidHelper.RequireObjectFrom(waterParkGuid);
            WaterPark  waterPark   = waterParkGo.RequireComponent <WaterPark>();

            waterPark.AddItem(pickupable);
        }
        protected override void SpawnPostProcess(Base latestBase, Int3 latestCell, GameObject finishedPiece)
        {
            NitroxId pieceId = NitroxEntity.GetId(finishedPiece);

            WaterParkPiece waterParkPiece = finishedPiece.GetComponent <WaterParkPiece>();

            if (!waterParkPiece)
            {
                // The BaseWater has multiple base pieces, but only one of them (the bottom) contains the WaterParkPiece component...
                return;
            }

            WaterPark waterPark = waterParkPiece.GetWaterParkModule();

            Validate.NotNull(waterPark, "WaterParkPiece without WaterParkModule?!?");

            // assuming there could be multiple pieces sharing the same waterpark we only create an ID if there is none.
            NitroxEntity waterEntity = waterPark.gameObject.GetComponent <NitroxEntity>();

            if (!waterEntity)
            {
                NitroxId newWaterparkId = pieceId.Increment();
                NitroxEntity.SetNewId(waterPark.gameObject, newWaterparkId);

                NitroxId newPlanterId = newWaterparkId.Increment();
                NitroxEntity.SetNewId(waterPark.planter.gameObject, newPlanterId);

                Log.Debug($"BaseRoomWaterParkProcessor: Created new Waterpark {newWaterparkId} and Planter {newPlanterId}");
            }
        }
Beispiel #5
0
        // The next two functions could potentially reside outside of this specific serializer.
        // They only happen to be in here because dropped items use this code path.

        private void AssignToWaterPark(GameObject gameObject, string waterParkGuid)
        {
            Pickupable pickupable  = gameObject.RequireComponent <Pickupable>();
            GameObject waterParkGo = GuidHelper.RequireObjectFrom(waterParkGuid);
            WaterPark  waterPark   = waterParkGo.RequireComponent <WaterPark>();

            waterPark.AddItem(pickupable);
        }
Beispiel #6
0
        // The next two functions could potentially reside outside of this specific serializer.
        // They only happen to be in here because dropped items use this code path.

        private void AssignToWaterPark(GameObject gameObject, NitroxId waterParkId)
        {
            Pickupable pickupable  = gameObject.RequireComponent <Pickupable>();
            GameObject waterParkGo = NitroxEntity.RequireObjectFrom(waterParkId);
            WaterPark  waterPark   = waterParkGo.RequireComponent <WaterPark>();

            waterPark.AddItem(pickupable);
        }
        public static void Prefix(WaterPark __instance)
        {
#if BZ
            if (__instance is LargeRoomWaterPark)
            {
                __instance.wpPieceCapacity = Main.config.LargeWaterParkSize;
            }
            else
#endif
            __instance.wpPieceCapacity = Main.config.WaterParkSize;
        }
Beispiel #8
0
        private static IEnumerator SpawnCreature(WaterPark waterPark, TechType parkCreatureTechType, ItemsContainer container)
        {
            var task = CraftData.GetPrefabForTechTypeAsync(parkCreatureTechType, false);

            yield return(task);

            var prefab = task.GetResult();

            if (prefab == null)
            {
                yield break;
            }

            prefab.SetActive(false);
            var gameObject = Object.Instantiate(prefab);

            if (container is not null)
            {
                var 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
                gameObject.SetActive(false);
                container.AddItem(pickupable);
                yield break;
            }

            var spawnPoint = waterPark.transform.position + (Random.insideUnitSphere * 50);
            var @base      =
#if SN1
                waterPark.GetComponentInParent <Base>();
#elif BZ
                waterPark.hostBase;
#endif

            while (Vector3.Distance(@base.GetClosestPoint(spawnPoint), spawnPoint) < 25 || spawnPoint.y >= 0)
            {
                yield return(null);

                spawnPoint = @base.GetClosestPoint(spawnPoint) + (Random.insideUnitSphere * 50);
            }

            gameObject.transform.SetPositionAndRotation(spawnPoint, Quaternion.identity);
            gameObject.SetActive(true);
        }
Beispiel #9
0
        public static void Postfix(WaterPark __instance, WaterParkCreature creature)
        {
            if (!__instance.items.Contains(creature) || __instance.HasFreeSpace())
            {
                return;
            }

            List <BaseBioReactor> baseBioReactors = __instance.gameObject.GetComponentInParent <SubRoot>().gameObject.GetComponentsInChildren <BaseBioReactor>().ToList();
            bool hasBred = false;

            foreach (WaterParkItem waterParkItem in __instance.items)
            {
                WaterParkCreature parkCreature = waterParkItem as WaterParkCreature;
                if (parkCreature != null && parkCreature != creature && parkCreature.GetCanBreed() && parkCreature.pickupable.GetTechType() == creature.pickupable.GetTechType() && !parkCreature.pickupable.GetTechType().ToString().Contains("Egg"))
                {
                    foreach (BaseBioReactor baseBioReactor in baseBioReactors)
                    {
                        if (baseBioReactor.container.HasRoomFor(parkCreature.pickupable))
                        {
                            creature.ResetBreedTime();
                            parkCreature.ResetBreedTime();
                            GameObject gameObject = CraftData.InstantiateFromPrefab(CraftData.GetTechType(parkCreature.data.eggOrChildPrefab), false);
                            gameObject.SetActive(false);
                            baseBioReactor.container.AddItem(gameObject.EnsureComponent <Pickupable>());
                            hasBred = true;
                            break;
                        }
                    }
                    if (!hasBred && Config.OverFlowIntoOcean && parkCreature.data.isPickupableOutside)
                    {
                        creature.ResetBreedTime();
                        parkCreature.ResetBreedTime();
                        if (count > Config.WaterParkSize)
                        {
                            GameObject gameObject = CraftData.InstantiateFromPrefab(CraftData.GetTechType(parkCreature.gameObject), false);
                            gameObject.transform.position = __instance.gameObject.GetComponentInParent <SubRoot>().transform.position + new Vector3(Random.Range(-30, 30), Random.Range(-2, 30), Random.Range(-30, 30));
                            gameObject.SetActive(true);
                            count = 0;
                        }
                        else
                        {
                            count++;
                        }
                    }
                    break;
                }
            }
        }
        public static void Postfix(WaterPark __instance, WaterParkCreature creature)
        {
            List <WaterParkItem> items = __instance.items;

            if (!items.Contains(creature) || __instance.HasFreeSpace() || BaseBioReactor.GetCharge(creature.pickupable.GetTechType()) == -1)
            {
                return;
            }

            List <BaseBioReactor> baseBioReactors = __instance.gameObject.GetComponentInParent <SubRoot>().gameObject.GetComponentsInChildren <BaseBioReactor>().ToList();
            bool hasBred = false;

            foreach (WaterParkItem waterParkItem in items)
            {
                var      parkCreature         = waterParkItem as WaterParkCreature;
                TechType parkCreatureTechType = parkCreature?.pickupable?.GetTechType() ?? TechType.None;
                if (parkCreature != null && parkCreature != creature && parkCreature.GetCanBreed() && parkCreatureTechType == creature.pickupable.GetTechType() && !parkCreatureTechType.ToString().Contains("Egg"))
                {
                    if (BaseBioReactor.GetCharge(parkCreatureTechType) > -1)
                    {
                        if (QModServices.Main.ModPresent("FCSEnergySolutions"))
                        {
                            hasBred = AGT.TryBreedIntoAlterraGen(__instance, parkCreatureTechType, parkCreature);
                        }

                        if (!hasBred)
                        {
                            foreach (BaseBioReactor baseBioReactor in baseBioReactors)
                            {
                                if (baseBioReactor.container.HasRoomFor(parkCreature.pickupable))
                                {
                                    creature.ResetBreedTime();
                                    parkCreature.ResetBreedTime();
                                    hasBred = true;
                                    CoroutineHost.StartCoroutine(SpawnCreature(__instance, parkCreature, baseBioReactor.container));
                                    break;
                                }
                            }
                        }
                    }

                    creature.ResetBreedTime();
                    parkCreature.ResetBreedTime();
                    break;
                }
            }
        }
Beispiel #11
0
        private Optional <NitroxId> GetCurrentWaterParkId()
        {
            Player player = Utils.GetLocalPlayer().GetComponent <Player>();

            if (player != null)
            {
                WaterPark currentWaterPark = player.currentWaterPark;

                if (currentWaterPark != null)
                {
                    NitroxId waterParkId = NitroxEntity.GetId(currentWaterPark.gameObject);
                    return(Optional.Of(waterParkId));
                }
            }

            return(Optional.Empty);
        }
Beispiel #12
0
        private Optional <String> GetCurrentWaterParkGuid()
        {
            Player player = Utils.GetLocalPlayer().GetComponent <Player>();

            if (player != null)
            {
                WaterPark currentWaterPark = player.currentWaterPark;

                if (currentWaterPark != null)
                {
                    String waterParkGuid = GuidHelper.GetGuid(currentWaterPark.gameObject);
                    return(Optional <String> .Of(waterParkGuid));
                }
            }

            return(Optional <String> .Empty());
        }
Beispiel #13
0
        public static bool TryBreedIntoAlterraGen(WaterPark waterPark, TechType parkCreatureTechType, WaterParkCreature parkCreature)
        {
            var AlterraGens = waterPark?.gameObject?.GetComponentInParent <SubRoot>()?.gameObject?.GetComponentsInChildren <IFCSStorage>();

            if (AlterraGens is null)
            {
                return(false);
            }

            foreach (IFCSStorage storage in AlterraGens)
            {
                if (storage.GetType().Name.Contains("AlterraGen") && storage.IsAllowedToAdd(parkCreature.pickupable, false))
                {
                    CoroutineHost.StartCoroutine(AddItemToAlterraGen(parkCreatureTechType, storage));
                    return(true);
                }
            }

            return(false);
        }
Beispiel #14
0
        private void AssignToWaterPark(String waterParkGuid, Pickupable pickupable)
        {
            Optional <GameObject> opWaterPark = GuidHelper.GetObjectFrom(waterParkGuid);

            if (opWaterPark.IsPresent())
            {
                WaterPark waterPark = opWaterPark.Get().GetComponent <WaterPark>();

                if (waterPark != null)
                {
                    waterPark.AddItem(pickupable);
                }
                else
                {
                    Console.WriteLine("Could not find water park component on that game object");
                }
            }
            else
            {
                Console.WriteLine("Could not locate water park with guid: " + waterParkGuid);
            }
        }
Beispiel #15
0
        public static void Postfix(WaterPark __instance)
        {
            PowerSource powerSource      = __instance.gameObject.GetComponent <PowerSource>();
            int         numberOfShockers = __instance.items.FindAll((WaterParkItem item) => item.pickupable.GetTechType() == TechType.Shocker).Count;

            if (powerSource == null)
            {
                powerSource          = __instance.gameObject.AddComponent <PowerSource>();
                powerSource.maxPower = 100 * numberOfShockers;
                powerSource.power    = PlayerPrefs.GetFloat($"PowerSource:{__instance.GetInstanceID()}", 0f);
            }
            else
            {
                powerSource.maxPower = 100 * numberOfShockers;
            }
            if (powerSource.GetPower() > powerSource.GetMaxPower())
            {
                powerSource.power = powerSource.maxPower;
            }

            Config.PowerValues[$"PowerSource:{__instance.GetInstanceID()}"] = powerSource.GetPower();
        }
 public static bool Prefix(WaterPark waterPark, Vector3 position)
 {
     return(waterPark.IsPointInside(position));
 }
        public static void Postfix(WaterPark __instance)
        {
            List <WaterParkItem> powerCreatures = new List <WaterParkItem>();
            float maxPower = 0;

            if (cachedItems.TryGetValue(__instance, out List <WaterParkItem> items) && items.Count == __instance.items.Count && cachedPowerCreatures.ContainsKey(__instance))
            {
                powerCreatures.AddRange(cachedPowerCreatures[__instance]);

                foreach (var creature in cachedPowerCreatures[__instance])
                {
                    if (!creature.gameObject.TryGetComponent(out LiveMixin liveMixin) || !liveMixin.IsAlive())
                    {
                        powerCreatures.Remove(creature);
                    }
                }

                foreach (KeyValuePair <TechType, float> pair in Main.config.CreaturePowerGeneration)
                {
                    List <WaterParkItem> creatures = __instance.items.FindAll((WaterParkItem item) => item.pickupable.GetTechType() == pair.Key) ?? new List <WaterParkItem>();
                    if (creatures.Count > 0)
                    {
                        maxPower += 500 * pair.Value * creatures.Count;
                    }
                }

                cachedPowerCreatures[__instance] = powerCreatures;
            }
            else
            {
                foreach (KeyValuePair <TechType, float> pair in Main.config.CreaturePowerGeneration)
                {
                    List <WaterParkItem> creatures = __instance.items.FindAll((WaterParkItem item) => item.pickupable.GetTechType() == pair.Key && (item.GetComponent <LiveMixin>()?.IsAlive() ?? false)) ?? new List <WaterParkItem>();
                    if (creatures.Count > 0)
                    {
                        maxPower += 500 * pair.Value * creatures.Count;
                        powerCreatures.AddRange(creatures);
                    }
                }

                cachedItems[__instance]          = __instance.items;
                cachedPowerCreatures[__instance] = powerCreatures;
            }

            PowerSource powerSource = __instance?.itemsRoot?.gameObject?.GetComponent <PowerSource>();

            if (powerSource is null)
            {
                powerSource          = __instance?.itemsRoot?.gameObject?.AddComponent <PowerSource>();
                powerSource.maxPower = maxPower;
                powerSource.power    = Main.config.PowerValues.GetOrDefault($"PowerSource:{__instance.GetInstanceID()}", 0f);
            }
            else
            {
                if (powerSource.maxPower != maxPower)
                {
                    powerSource.maxPower = maxPower;
                }

                if (powerSource.power > powerSource.maxPower)
                {
                    powerSource.power = powerSource.maxPower;
                }

                Main.config.PowerValues[$"PowerSource:{__instance.GetInstanceID()}"] = powerSource.power;
            }

            timeSinceLastPositionCheck += Time.deltaTime;
            if (timeSinceLastPositionCheck > 0.5f)
            {
                foreach (WaterParkItem waterParkItem in __instance.items)
                {
                    if (!__instance.IsPointInside(waterParkItem.transform.position))
                    {
                        Vector3 position = waterParkItem.transform.position;
                        __instance.EnsurePointIsInside(ref position);
                        waterParkItem.transform.position = position;
                    }
                }
                timeSinceLastPositionCheck = 0;
            }
        }
Beispiel #18
0
 public static void Prefix(WaterPark __instance)
 {
     __instance.wpPieceCapacity = Main.Config.WaterParkSize;
 }
Beispiel #19
0
        public static void Postfix(WaterPark __instance, WaterParkCreature creature)
        {
            if (!Main.Config.AlterraGenOverflow && !Main.Config.BioReactorOverflow && !Main.Config.OceanBreeding)
            {
                return;
            }

            var items    = __instance.items;
            var techType = creature.pickupable.GetTechType();

            if (!items.Contains(creature) || __instance.HasFreeSpace() || BaseBioReactor.GetCharge(techType) <= 0f)
            {
                return;
            }

            var hasBred = false;

            foreach (var waterParkItem in items)
            {
                var parkCreature         = waterParkItem as WaterParkCreature;
                var parkCreatureTechType = parkCreature is not null && parkCreature.pickupable != null?parkCreature.pickupable.GetTechType() : TechType.None;

                if (parkCreature == null || parkCreature == creature || !parkCreature.GetCanBreed() ||
                    parkCreatureTechType != techType || parkCreatureTechType.ToString().Contains("Egg"))
                {
                    continue;
                }

                if (BaseBioReactor.GetCharge(parkCreatureTechType) > -1)
                {
                    if (Main.Config.AlterraGenOverflow && !Main.Config.AlterraGenBlackList.Contains(parkCreatureTechType) && QModServices.Main.ModPresent("FCSEnergySolutions"))
                    {
                        hasBred = AGT.TryBreedIntoAlterraGen(__instance, parkCreatureTechType, parkCreature);
                    }

                    if (Main.Config.BioReactorOverflow && !Main.Config.BioReactorBlackList.Contains(parkCreatureTechType) && !hasBred)
                    {
                        var baseBioReactors =
                            __instance.gameObject.GetComponentInParent <SubRoot>()?.gameObject
                            .GetComponentsInChildren <BaseBioReactor>()
                            ?.Where(baseBioReactor => baseBioReactor.container.HasRoomFor(parkCreature.pickupable))
                            .ToList() ?? new List <BaseBioReactor>();

                        if (baseBioReactors.Count > 0)
                        {
                            hasBred = true;
                            baseBioReactors.Shuffle();
                            var baseBioReactor = baseBioReactors.First();
                            CoroutineHost.StartCoroutine(SpawnCreature(__instance, parkCreatureTechType, baseBioReactor.container));
                        }
                    }

                    if (Main.Config.OceanBreeding && Main.Config.OceanBreedWhiteList.Contains(parkCreatureTechType) && !hasBred && __instance.transform.position.y < 0)
                    {
                        CoroutineHost.StartCoroutine(SpawnCreature(__instance, parkCreatureTechType, null));
                        hasBred = true;
                    }
                }

                if (hasBred)
                {
                    creature.ResetBreedTime();
                    parkCreature.ResetBreedTime();
                }
                break;
            }
        }
        public static void Postfix(Player __instance)
        {
            PlayerTool heldTool = Inventory.main.GetHeldTool();
            Vehicle    vehicle  = __instance.GetVehicle();
            Pickupable module   = vehicle?.GetSlotItem(vehicle.GetActiveSlotID())?.item;

            bool builderCheck       = heldTool?.pickupable?.GetTechType() == TechType.Builder;
            bool builderModuleCheck = module != null && TechTypeHandler.TryGetModdedTechType("BuilderModule", out TechType modTechType) && module.GetTechType() == modTechType;

            string msg1 = $"Attach as target override = {Main.config.AttachToTarget}";

            ErrorMessage._Message emsg = ErrorMessage.main.GetExistingMessage(msg1);
            string msg2 = $"Full Override = {Main.config.FullOverride}";

            ErrorMessage._Message emsg2 = ErrorMessage.main.GetExistingMessage(msg2);

            if (DevConsole.instance != null && !DevConsole.instance.state && (builderCheck || builderModuleCheck))
            {
                if (Input.GetKeyDown(Main.config.AttachToTargetToggle))
                {
                    Main.config.AttachToTarget = !Main.config.AttachToTarget;
                    msg1 = $"Attach as target override = {Main.config.AttachToTarget}";
                }

                if (Input.GetKeyDown(Main.config.FullOverrideToggle))
                {
                    Main.config.FullOverride = !Main.config.FullOverride;
                    msg2 = $"Full Override = {Main.config.FullOverride}";
                }

                if (emsg != null)
                {
                    emsg.messageText = msg1;
                    emsg.entry.text  = msg1;
                    if (emsg.timeEnd <= Time.time + 1f)
                    {
                        emsg.timeEnd += Time.deltaTime;
                    }
                }
                else
                {
                    ErrorMessage.AddMessage(msg1);
                }

                if (emsg2 != null)
                {
                    emsg2.messageText = msg2;
                    emsg2.entry.text  = msg2;

                    if (emsg2.timeEnd <= Time.time + 1f)
                    {
                        emsg2.timeEnd += Time.deltaTime;
                    }
                }
                else
                {
                    ErrorMessage.AddMessage(msg2);
                }
            }
            else if (Main.config.AttachToTarget || Main.config.FullOverride)
            {
                Main.config.AttachToTarget = false;
                Main.config.FullOverride   = false;

                if (emsg != null)
                {
                    emsg.timeEnd = Time.time;
                }

                if (emsg2 != null)
                {
                    emsg2.timeEnd = Time.time;
                }
            }

            WaterPark waterPark = __instance?.currentWaterPark;

            if (waterPark?.GetComponentInParent <Creature>() != null)
            {
                Vector3 vector3 = __instance.currentWaterPark.transform.position;
                __instance.SetPosition(vector3);

                string msg3 = $"Press {GameInput.GetBinding(GameInput.GetPrimaryDevice(), GameInput.Button.Exit, GameInput.BindingSet.Primary)} to exit waterpark if you cant reach the exit.";
                ErrorMessage._Message emsg3 = ErrorMessage.main.GetExistingMessage(msg3);
                if (emsg3 != null && emsg3.timeEnd <= Time.time + 1f)
                {
                    emsg3.timeEnd += Time.deltaTime;
                }
                else if (emsg3 is null)
                {
                    ErrorMessage.AddMessage(msg3);
                }

                if (GameInput.GetButtonDown(GameInput.Button.Exit))
                {
                    UseableDiveHatch diveHatch = null;

                    Collider[] hitColliders = Physics.OverlapSphere(__instance.transform.position, 3f, 1, QueryTriggerInteraction.UseGlobal);
                    foreach (Collider hitCollider in hitColliders)
                    {
                        UseableDiveHatch hatch = hitCollider.gameObject.GetComponentInParent <UseableDiveHatch>();
                        if (hatch != null && hatch.isForWaterPark)
                        {
                            diveHatch = hatch;
                            break;
                        }
                    }

                    if (diveHatch != null)
                    {
                        diveHatch.StartCinematicMode(diveHatch.enterCinematicController, __instance);
                        if (diveHatch.enterCustomGoalText != "" && (!diveHatch.customGoalWithLootOnly || Inventory.main.GetTotalItemCount() > 0))
                        {
                            Debug.Log("OnCustomGoalEvent(" + diveHatch.enterCustomText);
                            GoalManager.main.OnCustomGoalEvent(diveHatch.enterCustomGoalText);
                        }
                        if (diveHatch.secureInventory)
                        {
                            Inventory.Get().SecureItems(true);
                        }
                    }
                }
                return;
            }

#if SN1
            SubRoot currentSubRoot = __instance.GetCurrentSub();
            if (currentSubRoot != null && currentSubRoot is BaseRoot && __instance.playerController.velocity.y < -20f)
            {
                RespawnPoint componentInChildren = currentSubRoot.gameObject.GetComponentInChildren <RespawnPoint>();
                if (componentInChildren)
                {
                    __instance.SetPosition(componentInChildren.GetSpawnPosition());
                    return;
                }
            }

            EscapePod escapePod = __instance.currentEscapePod;
            if (escapePod != null && __instance.playerController.velocity.y < -20f)
            {
                __instance.SetPosition(escapePod.playerSpawn.transform.position, escapePod.playerSpawn.transform.rotation);
                return;
            }
#elif BZ
            IInteriorSpace interiorSpace = __instance.currentInterior;
            if (interiorSpace != null && __instance.playerController.velocity.y < -20f)
            {
                RespawnPoint respawnPoint = interiorSpace.GetRespawnPoint();
                if (respawnPoint)
                {
                    __instance.SetPosition(respawnPoint.GetSpawnPosition());
                    return;
                }
            }
#endif
        }
Beispiel #21
0
        // ReSharper disable once InconsistentNaming
        private static bool Prefix(WaterPark __instance, WaterParkCreature creature)
        {
            FishOverflowDistributor.Logger.LogTrace("WaterPark.TryBreed(WaterParkCreature) called.");

            //We only distribute when the WaterPark doesn't have any space left for bred creatures.
            //This is the only place in this method where we allow the original unpatched method to execute,
            //because the original method is never executed when there is no space left in the WaterPark.

            FishOverflowDistributor.Logger.LogTrace(
                $"__instance.HasFreeSpace() returns '{__instance.HasFreeSpace()}'.");

            if (__instance.HasFreeSpace())
            {
                return(true);
            }

            //using Harmony's Traverse class for reflection. Harmony caches MethodInfo, FieldInfo, etc. for further use and thus increases performance.
            var items = Traverse
                        .Create(__instance)
                        .Field("items")
                        .GetValue <List <WaterParkItem> >();

            if (items == null)
            {
                FishOverflowDistributor.Logger.LogError(
                    "FieldInfo or value for field 'items' in class 'WaterParkItem' with type 'List<WaterParkItem>' was null -> Should not happen, investigate!.");

                return(false);
            }


            FishOverflowDistributor.Logger.LogTrace("Checking if creature is contained in items");

            //Don't know why this check is needed. Maybe TryBreed gets called on fish which arent contained in this WaterPark instance.
            if (!items.Contains(creature))
            {
                return(false);
            }

            TechType creatureTechType = creature.pickupable.GetTechType();

            FishOverflowDistributor.Logger.LogTrace($"Creature Tech Type = {creatureTechType.ToString()}.");

            FishOverflowDistributor.Logger.LogTrace(
                "Checking whether creatureEggs.containsKey(creatureTechType)");

            //we don't want to distribute creature eggs
            if (WaterParkCreature.creatureEggs.ContainsKey(creatureTechType))
            {
                return(false);
            }

            FishOverflowDistributor.Logger.LogTrace(
                $"Waterpark '{__instance.gameObject.name}' contains creature '{creature.gameObject.name}' and has enough space for another one.");

            var secondCreature = items.Find(item =>
                                            item != creature &&
                                            item is WaterParkCreature &&

                                            // ReSharper disable once TryCastAlwaysSucceeds
                                            (item as WaterParkCreature).GetCanBreed() &&
                                            item.pickupable != null &&
                                            item.pickupable.GetTechType() == creatureTechType) as
                                 WaterParkCreature;

            if (secondCreature == null)
            {
                return(false);
            }

            FishOverflowDistributor.Logger.LogTrace(
                $"Waterpark contains two creatures '{creature.gameObject.name}' of TechType '{creatureTechType.ToString()}' which can breed with each other.");

            BaseBioReactor suitableReactor;

            try
            {
                //Get a reactor which has space for the item in the same base
                suitableReactor = SubnauticaSceneTraversalUtils
                                  .GetComponentsInSameBase <BaseBioReactor>(__instance.gameObject)
                                  .First(
                    reactor =>
                {
                    var itemsContainer = Traverse
                                         .Create(reactor)
                                         .Property("container")
                                         .GetValue <ItemsContainer>();

                    if (itemsContainer != null)
                    {
                        return(itemsContainer.HasRoomFor(
                                   creature.pickupable));
                    }

                    FishOverflowDistributor.Logger.LogTrace(
                        $"PropertyInfo or value for property 'container' in class 'BaseBioReactor' with type 'ItemsContainer' was null -> Should not happen, investigate!.");

                    return(false);
                });
            }
            catch (Exception)
            {
                return(false);
            }
            if (suitableReactor == null)
            {
                FishOverflowDistributor.Logger.LogTrace("Could not find suitable reactor");
                return(false);
            }

            //Reset breed time of the second creature so it can't be used to immediately breed again.
            secondCreature.ResetBreedTime();

            FishOverflowDistributor.Logger.LogTrace(
                $"Found suitable reactor '{suitableReactor.gameObject.name}'.");

            //Now we create a pickupable from the WaterParkCreature which we can add to the reactor's inventory.
            //Because the creature can't be taken out from the reactor inventory, we don't need to add WaterparkCreature component
            //to it. This would be needed so the game knows when you drop it outside, that it came from a waterpark.


            GameObject newCreature = CraftData.InstantiateFromPrefab(creatureTechType, false);

            newCreature.SetActive(false);
            newCreature.transform.position = creature.transform.position + Vector3.down;
            var pickupable = newCreature.EnsureComponent <Pickupable>();

            /*WaterParkCreatureParameters creatureParameters =
             *  WaterParkCreature.GetParameters(creatureTechType);
             *
             * newCreature.transform.localScale = creatureParameters.initialSize * Vector3.one;
             * var newCreatureComponent = newCreature.AddComponent<WaterParkCreature>();
             * newCreatureComponent.age = 0f;
             *
             * Traverse
             *  .Create(newCreatureComponent)
             *  .Field("parameters")
             *  .SetValue(creatureParameters);
             *
             * Pickupable pickupable = creatureParameters.isPickupableOutside
             *  ? newCreature.EnsureComponent<Pickupable>()
             *  : newCreature.GetComponent<Pickupable>();
             *
             * newCreature.setActive();*/

            pickupable = pickupable.Pickup(false);

            // pickupable.GetComponent<WaterParkItem>()?.SetWaterPark(null);

            var itemToAdd = new InventoryItem(pickupable);

            var reactorItemsContainer = Traverse
                                        .Create(suitableReactor)
                                        .Property("container")
                                        .GetValue <ItemsContainer>();

            if (reactorItemsContainer == null)
            {
                FishOverflowDistributor.Logger.LogError(
                    $"PropertyInfo or value for property 'container' in class 'BaseBioReactor' with type 'ItemsContainer' was null -> Should not happen, investigate!.");

                return(false);
            }

            reactorItemsContainer.AddItem(pickupable);

            return(false);
        }