/// <summary>
        /// Gets the prefab game object
        /// </summary>
        public sealed override GameObject GetGameObject()
        {
            V2.Logger.Debug($"[FishFramework] Initializing fish: {this.ClassID}");
            GameObject mainObj = modelPrefab;

            Renderer[] renderers = mainObj.GetComponentsInChildren <Renderer>();
            foreach (Renderer rend in renderers)
            {
                rend.material.shader = Shader.Find("MarmosetUBER");
            }

            Rigidbody rb = mainObj.EnsureComponent <Rigidbody>();

            rb.useGravity  = false;
            rb.angularDrag = 1f;

            WorldForces forces = mainObj.EnsureComponent <WorldForces>();

            forces.useRigidbody      = rb;
            forces.aboveWaterDrag    = 0f;
            forces.aboveWaterGravity = 9.81f;
            forces.handleDrag        = true;
            forces.handleGravity     = true;
            forces.underwaterDrag    = 1f;
            forces.underwaterGravity = 0;
#if BELOWZERO || SUBNAUTICA_EXP
            forces.waterDepth = Ocean.GetOceanLevel();
#else
            forces.waterDepth = Ocean.main.GetOceanLevel();
#endif
            forces.enabled = false;
            forces.enabled = true;

            mainObj.EnsureComponent <EntityTag>().slotType         = EntitySlot.Type.Creature;
            mainObj.EnsureComponent <PrefabIdentifier>().ClassId   = this.ClassID;
            mainObj.EnsureComponent <TechTag>().type               = this.TechType;
            mainObj.EnsureComponent <SkyApplier>().renderers       = renderers;
            mainObj.EnsureComponent <LargeWorldEntity>().cellLevel = LargeWorldEntity.CellLevel.Near;
            mainObj.EnsureComponent <LiveMixin>().health           = 10f;

            Creature creature = mainObj.EnsureComponent <Creature>();
            creature.initialCuriosity    = AnimationCurve.Linear(0f, 0.5f, 1f, 0.5f);
            creature.initialFriendliness = AnimationCurve.Linear(0f, 0.5f, 1f, 0.5f);
            creature.initialHunger       = AnimationCurve.Linear(0f, 0.5f, 1f, 0.5f);

            SwimBehaviour behaviour = null;
            if (isWaterCreature)
            {
                behaviour = mainObj.EnsureComponent <SwimBehaviour>();
                SwimRandom swim = mainObj.EnsureComponent <SwimRandom>();
                swim.swimVelocity = swimSpeed;
                swim.swimRadius   = swimRadius;
                swim.swimInterval = swimInterval;
            }
            else
            {
                behaviour = mainObj.EnsureComponent <WalkBehaviour>();
                WalkOnGround      walk = mainObj.EnsureComponent <WalkOnGround>();
                OnSurfaceMovement move = mainObj.EnsureComponent <OnSurfaceMovement>();
                move.onSurfaceTracker = mainObj.EnsureComponent <OnSurfaceTracker>();
            }

            Locomotion loco = mainObj.EnsureComponent <Locomotion>();
            loco.useRigidbody = rb;

            mainObj.EnsureComponent <EcoTarget>().type = EcoTargetType.Peeper;
            mainObj.EnsureComponent <CreatureUtils>();
            mainObj.EnsureComponent <VFXSchoolFishRepulsor>();

            SplineFollowing spline = mainObj.EnsureComponent <SplineFollowing>();
            spline.locomotion    = loco;
            spline.levelOfDetail = mainObj.EnsureComponent <BehaviourLOD>();
            spline.GoTo(mainObj.transform.position + mainObj.transform.forward, mainObj.transform.forward, 5f);

            behaviour.splineFollowing = spline;

            if (pickupable)
            {
                mainObj.EnsureComponent <Pickupable>();
            }

            creature.ScanCreatureActions();

            return(mainObj);
        }
        public static void Postfix(Creature __instance, ref CreatureAction __result, List <CreatureAction> ___actions, CreatureAction ___prevBestAction,
                                   int ___indexLastActionChecked)
        {
            float distToPlayer = Vector3.Distance(Player.main.transform.position, __instance.transform.position);

            /*
             * if (__instance.name.Contains("GhostLeviathan"))
             * {
             *      Logger.Output("Dist: " + distToPlayer);
             * }
             */

            // Determine the effectiveness of our module
            float myMaxRange;

            switch (StealthModulePatcher.stealthQuality)
            {
            case (StealthQuality.None):
                myMaxRange = float.MaxValue;
                break;

            case (StealthQuality.Low):
                myMaxRange = 80f;
                break;

            case (StealthQuality.Medium):
                myMaxRange = 60f;
                break;

            case (StealthQuality.High):
                myMaxRange = 40f;
                break;

            case (StealthQuality.Debug):
                myMaxRange = float.MinValue;
                break;

            default:
                myMaxRange = float.MaxValue;
                break;
            }

            if (StealthModulePatcher.stealthQuality == StealthQuality.None)
            {
                return;
            }

            if (___actions.Count == 0)
            {
                __result = null;
                return;
            }
            if (__instance.liveMixin && !__instance.liveMixin.IsAlive())
            {
                SwimBehaviour component = __instance.transform.root.GetComponent <SwimBehaviour>();
                if (component)
                {
                    component.Idle();
                }
                __result = null;
                return;
            }
            float          num            = 0f;
            CreatureAction creatureAction = null;

            if (___prevBestAction != null)
            {
                creatureAction = ___prevBestAction;

                // check if this action is violent
                string actionName1 = creatureAction.GetType().Name;
                // || actionName1 == "MoveTowardsTarget"
                if (actionName1 == "AttackLastTarget" || actionName1 == "AttackCyclops" || actionName1 == "EMPAttack" || actionName1 == "MushroomAttack")
                {
                    // check whether we're in range of the player
                    if (distToPlayer < myMaxRange)
                    {
                        // continue as usual
                    }
                    else
                    {
                        // special case for AttackLastTarget... target could be not the player
                        if (actionName1 == "AttackLastTarget")
                        {
                            if (((AttackLastTarget)creatureAction).lastTarget.target)
                            {
                                if (((AttackLastTarget)creatureAction).lastTarget.target.name == "Player")
                                {
                                    Logger.Log(__instance.name + " is replacing " + creatureAction.GetType().Name + "(Player) with SwimRandom.");
                                    creatureAction = new SwimRandom();
                                }
                            }
                        }
                        else
                        {
                            Logger.Log(__instance.name + " is replacing " + creatureAction.GetType().Name + " with SwimRandom.");
                            creatureAction = new SwimRandom();
                        }
                    }
                }

                num = creatureAction.Evaluate(__instance);
            }
            ___indexLastActionChecked++;
            if (___indexLastActionChecked >= ___actions.Count)
            {
                ___indexLastActionChecked = 0;
            }

            CreatureAction creatureAction2 = ___actions[___indexLastActionChecked];

            // check if this action is violent
            string actionName2 = creatureAction2.GetType().Name;

            if (actionName2 == "AttackLastTarget" || actionName2 == "AttackCyclops" || actionName2 == "EMPAttack" || actionName2 == "MushroomAttack")
            {
                // check whether we're in range of the player
                if (distToPlayer < myMaxRange)
                {
                    // continue as usual
                }
                else
                {
                    // special case for AttackLastTarget... target could be not the player
                    if (actionName2 == "AttackLastTarget")
                    {
                        if (((AttackLastTarget)creatureAction2).lastTarget.target)
                        {
                            if (((AttackLastTarget)creatureAction2).lastTarget.target.name == "Player")
                            {
                                Logger.Log(__instance.name + " is replacing " + creatureAction2.GetType().Name + "(Player) with SwimRandom (2)");
                                creatureAction2 = new SwimRandom();
                            }
                        }
                    }
                    else
                    {
                        Logger.Log(__instance.name + " is replacing " + creatureAction2.GetType().Name + " with SwimRandom (2)");
                        creatureAction2 = new SwimRandom();
                    }
                }
            }

            float num2 = creatureAction2.Evaluate(__instance);

            if (num2 > num && !global::Utils.NearlyEqual(num2, 0f, 1E-45f))
            {
                creatureAction = creatureAction2;
            }

            __result = creatureAction;
            return;
        }
        public override GameObject GetGameObject()
        {
            Console.WriteLine("[FishFramework] Getting object from asset bundle");
            GameObject mainObj = bundle.LoadAsset <GameObject>(PrefabFileName);

            mainObj.AddComponent <ScaleFixer>().scale = scale;

            Console.WriteLine("[FishFramework] Setting correct shaders on renderers");
            Renderer[] renderers = mainObj.GetComponentsInChildren <Renderer>();
            foreach (Renderer rend in renderers)
            {
                rend.material.shader = Shader.Find("MarmosetUBER");
            }

            Console.WriteLine("[FishFramework] Adding essential components to object");

            Rigidbody rb = mainObj.AddOrGet <Rigidbody>();

            rb.useGravity  = false;
            rb.angularDrag = 1f;

            WorldForces forces = mainObj.AddOrGet <WorldForces>();

            forces.useRigidbody      = rb;
            forces.aboveWaterDrag    = 0f;
            forces.aboveWaterGravity = 9.81f;
            forces.handleDrag        = true;
            forces.handleGravity     = true;
            forces.underwaterDrag    = 1f;
            forces.underwaterGravity = 0;
            forces.waterDepth        = Ocean.main.GetOceanLevel();
            forces.enabled           = false;
            forces.enabled           = true;

            mainObj.AddOrGet <EntityTag>().slotType       = EntitySlot.Type.Creature;
            mainObj.AddOrGet <PrefabIdentifier>().ClassId = ClassID;
            mainObj.AddOrGet <TechTag>().type             = TechType;

            mainObj.AddOrGet <SkyApplier>().renderers       = renderers;
            mainObj.AddOrGet <LargeWorldEntity>().cellLevel = LargeWorldEntity.CellLevel.Near;
            mainObj.AddOrGet <LiveMixin>().health           = 10f;

            Creature creature = mainObj.AddOrGet <Creature>();

            creature.initialCuriosity    = AnimationCurve.Linear(0f, 0.5f, 1f, 0.5f);
            creature.initialFriendliness = AnimationCurve.Linear(0f, 0.5f, 1f, 0.5f);
            creature.initialHunger       = AnimationCurve.Linear(0f, 0.5f, 1f, 0.5f);
            SwimBehaviour behaviour = null;

            if (isWaterCreature)
            {
                behaviour = mainObj.AddOrGet <SwimBehaviour>();
                SwimRandom swim = mainObj.AddOrGet <SwimRandom>();
                swim.swimVelocity = swimSpeed;
                swim.swimRadius   = swimRadius;
                swim.swimInterval = 1f;
            }
            else
            {
                behaviour = mainObj.AddOrGet <WalkBehaviour>();
                WalkOnGround      walk = mainObj.AddOrGet <WalkOnGround>();
                OnSurfaceMovement move = mainObj.AddOrGet <OnSurfaceMovement>();
                move.onSurfaceTracker = mainObj.AddOrGet <OnSurfaceTracker>();
            }
            Locomotion loco = mainObj.AddOrGet <Locomotion>();

            loco.useRigidbody = rb;
            mainObj.AddOrGet <EcoTarget>().type = EcoTargetType.Peeper;
            mainObj.AddOrGet <CreatureUtils>();
            mainObj.AddOrGet <VFXSchoolFishRepulsor>();
            SplineFollowing spline = mainObj.AddOrGet <SplineFollowing>();

            spline.locomotion    = loco;
            spline.levelOfDetail = mainObj.AddOrGet <BehaviourLOD>();
            spline.GoTo(mainObj.transform.position + mainObj.transform.forward, mainObj.transform.forward, 5f);
            behaviour.splineFollowing = spline;
            creature.ScanCreatureActions();

            Console.WriteLine("[FishFramework] Adding pickupable component");
            if (pickupable)
            {
                mainObj.AddOrGet <Pickupable>();
            }

            Console.WriteLine("[FishFramework] Adding custom components");

            foreach (Type type in componentsToAdd)
            {
                try
                {
                    mainObj.AddComponent(type);
                }
                catch
                {
                    Console.WriteLine("[FishFramework] Failed to add component " + type.Name + " to GameObject");
                }
            }

            return(mainObj);
        }
Example #4
0
 public CreatureSpeedConfig(SwimRandom swimRandom, long techTypeHash, float originVelocity)
 {
     this.SwimRandom     = swimRandom;
     this.TechTypeHash   = techTypeHash;
     this.OriginVelocity = originVelocity;
 }