Example #1
0
        /// <summary>
        /// Define root of chain >> _tc_rootBone - root bone of tail chain >> TailBones[0] or GhostParent
        /// </summary>
        void TailCalculations_Begin()
        {
            if (IncludeParent) // Include first bone in chain to be modified
            {
                _tc_startI   = 0;
                _tc_rootBone = TailSegments[0];
            }
            else // Leaving first bone in chain intact (exclude)
            {
                _tc_startI = 1;
                if (TailSegments.Count > 1)
                {
                    _tc_rootBone = TailSegments[1];
                }
                else
                {
                    _tc_rootBone = TailSegments[0]; _tc_startI = -1;
                }
            }

            _tc_startII = _tc_startI + 1;
            if (_tc_startII > TailSegments.Count - 1)
            {
                _tc_startII = -1;
            }

            if (Deflection > Mathf.Epsilon)
            {
                if (!_pp_initialized)
                {
                    InitializePostProcessing();
                }
            }


            if (Tangle < 0)
            {
                _tc_tangle = Mathf.LerpUnclamped(1f, 1.5f, Tangle + 1f);
            }
            else
            {
                _tc_tangle = Mathf.LerpUnclamped(1f, -4f, Tangle);
            }
        }
        /// <summary>
        /// Initialize post processing reference points
        /// </summary>
        void InitializePostProcessing()
        {
            _pp_reference = new List <TailSegment>();

            // Generating copy of whole tail processing chain
            _pp_ref_rootParent = new TailSegment(GhostParent);
            for (int i = 0; i < TailSegments.Count; i++)
            {
                TailSegment bone = new TailSegment(TailSegments[i]); _pp_reference.Add(bone);
            }
            _pp_ref_lastChild = new TailSegment(GhostChild);


            // Setting child parent relation
            _pp_ref_rootParent.SetChildRef(_pp_reference[0]);                                   // root have just child
            _pp_ref_rootParent.SetParentRef(new TailSegment(GhostParent.ParentBone.transform)); // Safety parent

            for (int i = 0; i < _pp_reference.Count; i++)
            {
                TailSegment bone = _pp_reference[i];
                bone.SetIndex(i, TailSegments.Count);

                if (i == 0) // First bone have ghost parent
                {
                    bone.SetParentRef(_pp_ref_rootParent);
                    bone.SetChildRef(_pp_reference[i + 1]);
                }
                else if (i == _pp_reference.Count - 1) // last bone have ghost child
                {
                    bone.SetParentRef(_pp_reference[i - 1]);
                    bone.SetChildRef(_pp_ref_lastChild);
                }
                else // Default bone from chain middle points
                {
                    bone.SetParentRef(_pp_reference[i - 1]);
                    bone.SetChildRef(_pp_reference[i + 1]);
                }
            }

            _pp_ref_lastChild.SetParentRef(_pp_reference[_pp_reference.Count - 1]); // end have just parent


            _pp_initialized = true;
        }
Example #3
0
            /// <summary>
            /// Copying animation parameters from other segment
            /// </summary>
            internal void ParamsFrom(TailSegment other)
            {
                BlendValue           = other.BlendValue;
                ColliderRadius       = other.ColliderRadius;
                Gravity              = other.Gravity;
                LengthMultiplier     = other.LengthMultiplier;
                BoneLength           = other.BoneLength;
                BoneLengthScaled     = other.BoneLengthScaled;
                BoneDimensionsScaled = other.BoneDimensionsScaled;
                collisionContacts    = other.collisionContacts;
                CollisionHelper      = other.CollisionHelper;

                PositionSpeed = other.PositionSpeed;
                RotationSpeed = other.RotationSpeed;
                Springiness   = other.Springiness;
                Slithery      = other.Slithery;
                Curling       = other.Curling;
                Slippery      = other.Slippery;
            }
Example #4
0
        /// <summary>
        /// Begin update operations for additionaly genrated child bone of chain
        /// </summary>
        public void TailCalculations_UpdateArtificialChildBone(TailSegment child)
        {
            // Pre processing with limiting, gravity etc.
            //TailCalculations_SegmentPreProcessingStack(lastChild);

            //// Blending animation weight
            //TailSegment_PreRotationPositionBlend(lastChild);

            TailSegment_BaseSwingProcessing(child);

            if (child.PositionSpeed < 1f)
            {
                child.ProceduralPosition = TailCalculations_SmoothPosition(child.PreviousPosition /*+ _limiting_influenceOffset*/, child.ProceduralPosition, child);
            }

            if (MaxStretching < 1f)
            {
                StretchingLimiting(child);
            }

            if (!FEngineering.VIsZero(child.Gravity) || UseWind)
            {
                CalculateGravityPositionOffsetForSegment(child);
            }

            if (Axis2D > 0)
            {
                Axis2DLimit(child);
            }

            child.CollisionContactRelevancy = -1f;

            // Blending or just setting target position
            if (child.BlendValue * conditionalWeight < 1f)
            {
                child.ProceduralPositionWeightBlended = Vector3.LerpUnclamped(
                    child.ParentBone.transform.TransformPoint(child.LastKeyframeLocalPosition), child.ProceduralPosition, child.BlendValue * conditionalWeight);
            }
            else
            {
                child.ProceduralPositionWeightBlended = child.ProceduralPosition;
            }
        }
Example #5
0
        void TailCalculations_ComputeSegmentCollisions(TailSegment bone, ref Vector3 position)
        {
            // Computing collision contact timer
            if (bone.CollisionContactFlag)
            {
                bone.CollisionContactFlag = false;
            }
            else if (bone.CollisionContactRelevancy > 0f)
            {
                bone.CollisionContactRelevancy -= justDelta;
            }

            if (CollisionSpace == ECollisionSpace.Selective_Fast)
            {
                // Setting collision contact flag
                if (PushIfSegmentInsideCollider(bone, ref position))
                {
                    bone.CollisionContactFlag                = true;
                    bone.CollisionContactRelevancy           = justDelta * 7f;
                    bone.ChildBone.CollisionContactRelevancy = Mathf.Max(bone.ChildBone.CollisionContactRelevancy, justDelta * 3.5f);
                    if (bone.ChildBone.ChildBone != null)
                    {
                        bone.ChildBone.ChildBone.CollisionContactRelevancy = Mathf.Max(bone.ChildBone.CollisionContactRelevancy, justDelta * 3f);
                    }
                    //bone.ParentBone.CollisionContactRelevancy = Mathf.Max(bone.ParentBone.CollisionContactRelevancy, delta * 3f);
                }
            }
            else
            {
                // Setting collision contact flag
                if (UseCollisionContact(bone.Index, ref position))
                {
                    bone.CollisionContactFlag                = true;
                    bone.CollisionContactRelevancy           = justDelta * 7f;
                    bone.ChildBone.CollisionContactRelevancy = Mathf.Max(bone.ChildBone.CollisionContactRelevancy, justDelta * 3.5f);
                    if (bone.ChildBone.ChildBone != null)
                    {
                        bone.ChildBone.ChildBone.CollisionContactRelevancy = Mathf.Max(bone.ChildBone.CollisionContactRelevancy, justDelta * 3f);
                    }
                    //bone.ParentBone.CollisionContactRelevancy = Mathf.Max(bone.ParentBone.CollisionContactRelevancy, delta * 2f);
                }
            }
        }
Example #6
0
        /// <summary>
        /// Searching for deflection points on stored segments position
        /// before post processing with deflection to avoid jitter
        /// </summary>
        void Deflection_BeginUpdate()
        {
            // Defining constants for segments
            _defl_treshold = DeflectionStartAngle / 90f;
            float smoothTime = DeflectionSmooth / 9f;

            //for (int i = TailBones.Count-1; i >=_tc_startII; --i)
            for (int i = _tc_startII; i < TailSegments.Count; i++)
            {
                TailSegment ppChild = _pp_reference[i];

                // Checking deflection state to detect bend amount
                bool cleared = ppChild.CheckDeflectionState(_defl_treshold, smoothTime, rateDelta);

                // Detecting if deflection occured and adding as deflection source point
                if (!cleared)
                {
                    bool dependenciesMeet = true;

                    if (DeflectOnlyCollisions)
                    {
                        if (ppChild.CollisionContactRelevancy <= 0f)
                        {
                            dependenciesMeet = false; // No collision - no deflection
                        }
                    }
                    // Adding to deflection points list
                    if (dependenciesMeet)
                    {
                        Deflection_AddDeflectionSource(ppChild);
                    }
                    else
                    {
                        Deflection_RemoveDeflectionSource(ppChild);
                    }
                }
                else
                {
                    Deflection_RemoveDeflectionSource(ppChild);
                }
            }
        }
Example #7
0
 /// <summary>
 /// Copying all available parameters from other segment
 /// </summary>
 internal void ParamsFromAll(TailSegment other)
 {
     ParamsFrom(other);
     InitialLocalPosition            = other.InitialLocalPosition;
     InitialLocalRotation            = other.InitialLocalRotation;
     LastFinalPosition               = other.LastFinalPosition;
     LastFinalRotation               = other.LastFinalRotation;
     ProceduralPosition              = other.ProceduralPosition;
     ProceduralPositionWeightBlended = other.ProceduralPositionWeightBlended;
     TrueTargetRotation              = other.TrueTargetRotation;
     PosRefRotation = other.PosRefRotation;
     PreviousPosReferenceRotation = other.PreviousPosReferenceRotation;
     PreviousPosition             = other.PreviousPosition;
     BoneLength           = other.BoneLength;
     BoneDimensionsScaled = other.BoneDimensionsScaled;
     BoneLengthScaled     = other.BoneLengthScaled;
     LocalOffset          = other.LocalOffset;
     ColliderRadius       = other.ColliderRadius;
     VelocityHelper       = other.VelocityHelper;
     QVelocityHelper      = other.QVelocityHelper;
     PreviousPush         = other.PreviousPush;
 }
Example #8
0
        /// <summary>
        /// Preparing segment positioning parameters
        /// </summary>
        void TailSegment_PrepareVelocity(TailSegment child)
        {
            // Velocity change check
            _sg_push = (child.ProceduralPosition - child.PreviousPosition);

            // Remember actual position after using previous position memory
            child.PreviousPosition = child.ProceduralPosition;

            // Collision slippery modify
            float swinginess = _sg_springVelo;

            if (child.CollisionContactFlag)
            {
                swinginess *= child.Slippery;
            }

            // Tail Motion velocity motion base calculations
            child.ProceduralPosition += _sg_push * swinginess;

            // Remember previous push for sustain feature
            child.PreviousPush = _sg_push;
        }
Example #9
0
        /// <summary>
        /// Preparing motion parameters for individual segment settings
        /// </summary>
        void TailSegment_PrepareMotionParameters(TailSegment child)
        {
            // Remember bone scale referenced from initial position
            child.BoneDimensionsScaled = Vector3.Scale(child.ParentBone.transform.lossyScale * child.LengthMultiplier, child.LastKeyframeLocalPosition);
            child.BoneLengthScaled     = child.BoneDimensionsScaled.magnitude; //(child.ParentBone.transform.position - child.transform.position).magnitude * child.LengthMultiplier;

            //// Non-Slithery
            //_sg_curly = Mathf.LerpUnclamped(0.6f, 0.15f, child.Curling);
            //_sg_springVelo = Mathf.LerpUnclamped(0.65f, 0.9f, child.Springiness);

            //// Slithery Blend
            //_sg_curly = Mathf.Lerp(_sg_curly, Mathf.LerpUnclamped(0.99f, 0.135f, child.Curling), child.Slithery);
            //_sg_springVelo = Mathf.Lerp(_sg_springVelo, Mathf.LerpUnclamped(0.0f, 0.8f, child.Springiness), child.Slithery);

            // Non-Slithery
            _sg_curly      = Mathf.LerpUnclamped(0.5f, 0.125f, child.Curling);
            _sg_springVelo = Mathf.LerpUnclamped(0.65f, 0.9f, child.Springiness);

            // Slithery Blend
            _sg_curly      = Mathf.Lerp(_sg_curly, Mathf.LerpUnclamped(0.95f, 0.135f, child.Curling), child.Slithery);
            _sg_springVelo = Mathf.Lerp(_sg_springVelo, Mathf.LerpUnclamped(0.1f, 0.85f, child.Springiness), child.Slithery);
        }
Example #10
0
 void Expert_UpdateBlending()
 {
     if (UsePartialBlend)
     {
         if (KeysChanged(BlendCurve.keys, lastBlendCurvKeys)) // for (int i = 0; i < TailBones.Count; i++) TailBones[i].BlendValue = GetValueFromCurve(i, BlendCurve);//Mathf.Clamp(Mathf.Pow(GetValueFromCurve(i, BlendCurve), .3f /*3*/), 0f, 1.5f);
         {
             _ex_bone = TailSegments[0]; while (_ex_bone != null)
             {
                 _ex_bone.BlendValue = BlendCurve.Evaluate(_ex_bone.IndexOverlLength); _ex_bone = _ex_bone.ChildBone;
             }
         }
     }
     else
     {
         if (lastTailAnimatorAmount != TailAnimatorAmount)
         {
             _ex_bone = TailSegments[0]; while (_ex_bone != null)
             {
                 _ex_bone.BlendValue = TailAnimatorAmount; _ex_bone = _ex_bone.ChildBone;
             }
         }
     }
 }
Example #11
0
 void Expert_UpdateSlippery()
 {
     if (UseSlipperyCurve)
     {
         if (KeysChanged(SlipperyCurve.keys, lastSlipperyCurvKeys)) //for (int i = 0; i < TailBones.Count; i++) TailBones[i].Slippery = GetValueFromCurve(i, SlipperyCurve);
         {
             _ex_bone = TailSegments[0]; while (_ex_bone != null)
             {
                 _ex_bone.Slippery = SlipperyCurve.Evaluate(_ex_bone.IndexOverlLength); _ex_bone = _ex_bone.ChildBone;
             }
         }
     }
     else
     {
         if (lastSlippery != CollisionSlippery) //for (int i = 0; i < TailBones.Count; i++) TailBones[i].Slippery = CollisionSlippery;
         {
             _ex_bone = TailSegments[0]; while (_ex_bone != null)
             {
                 _ex_bone.Slippery = CollisionSlippery; _ex_bone = _ex_bone.ChildBone;
             }
         }
     }
 }
Example #12
0
 void Expert_UpdateCurling()
 {
     if (UseCurlingCurve)
     {
         if (KeysChanged(CurlingCurve.keys, lastCurlingCurvKeys)) //for (int i = 0; i < TailBones.Count; i++) TailBones[i].Curling = GetValueFromCurve(i, CurlingCurve);
         {
             _ex_bone = TailSegments[0]; while (_ex_bone != null)
             {
                 _ex_bone.Curling = CurlingCurve.Evaluate(_ex_bone.IndexOverlLength); _ex_bone = _ex_bone.ChildBone;
             }
         }
     }
     else
     {
         if (lastCurling != Curling)
         {
             _ex_bone = TailSegments[0]; while (_ex_bone != null)
             {
                 _ex_bone.Curling = Curling; _ex_bone = _ex_bone.ChildBone;
             }
         }
     }
 }
Example #13
0
 void Expert_UpdateSpringiness()
 {
     if (UseSpringCurve)
     {
         if (KeysChanged(SpringCurve.keys, lastSpringCurvKeys)) //for (int i = 0; i < TailBones.Count; i++) TailBones[i].Springiness = GetValueFromCurve(i, SpringCurve);
         {
             _ex_bone = TailSegments[0]; while (_ex_bone != null)
             {
                 _ex_bone.Springiness = SpringCurve.Evaluate(_ex_bone.IndexOverlLength); _ex_bone = _ex_bone.ChildBone;
             }
         }
     }
     else
     {
         if (lastSpringiness != Springiness) //for (int i = 0; i < TailBones.Count; i++) TailBones[i].Springiness = Springiness;
         {
             _ex_bone = TailSegments[0]; while (_ex_bone != null)
             {
                 _ex_bone.Springiness = Springiness; _ex_bone = _ex_bone.ChildBone;
             }
         }
     }
 }
Example #14
0
 void Expert_UpdatePosSpeed()
 {
     if (UsePosSpeedCurve)
     {
         if (KeysChanged(PosCurve.keys, lastPosCurvKeys)) // for (int i = 0; i < TailBones.Count; i++) TailBones[i].PositionSpeed = GetValueFromCurve(i, PosCurve);
         {
             _ex_bone = TailSegments[0]; while (_ex_bone != null)
             {
                 _ex_bone.PositionSpeed = PosCurve.Evaluate(_ex_bone.IndexOverlLength); _ex_bone = _ex_bone.ChildBone;
             }
         }
     }
     else
     {
         if (lastPosSpeeds != ReactionSpeed) // for (int i = 0; i < TailBones.Count; i++) TailBones[i].PositionSpeed = ReactionSpeed;
         {
             _ex_bone = TailSegments[0]; while (_ex_bone != null)
             {
                 _ex_bone.PositionSpeed = ReactionSpeed; _ex_bone = _ex_bone.ChildBone;
             }
         }
     }
 }
Example #15
0
 void Expert_UpdateRotSpeed()
 {
     if (UseRotSpeedCurve)
     {
         if (KeysChanged(RotCurve.keys, lastRotCurvKeys)) //for (int i = 0; i < TailBones.Count; i++) TailBones[i].RotationSpeed = GetValueFromCurve(i, RotCurve);
         {
             _ex_bone = TailSegments[0]; while (_ex_bone != null)
             {
                 _ex_bone.RotationSpeed = RotCurve.Evaluate(_ex_bone.IndexOverlLength); _ex_bone = _ex_bone.ChildBone;
             }
         }
     }
     else
     {
         if (lastRotSpeeds != RotationRelevancy) //for (int i = 0; i < TailBones.Count; i++) TailBones[i].RotationSpeed = RotationRelevancy;
         {
             _ex_bone = TailSegments[0]; while (_ex_bone != null)
             {
                 _ex_bone.RotationSpeed = RotationRelevancy; _ex_bone = _ex_bone.ChildBone;
             }
         }
     }
 }
Example #16
0
 public void SetChildRef(TailSegment child)
 {
     ChildBone = child;
 }
Example #17
0
 public void SetParentRef(TailSegment parent)
 {
     ParentBone = parent; BoneLength = (ProceduralPosition - ParentBone.ProceduralPosition).magnitude;
 }
        void UpdateTailAlgorithm()
        {
            TailCalculations_Begin();  // Root definition

            if (framesToSimulate != 0) // If framerate not defined then framesToSimulate is always == 1
            {
                if (UseCollision)
                {
                    BeginCollisionsUpdate();               // Updating colliders to collide with
                }
                // If post processing is needed we computing reference coordinates
                bool postProcesses = PostProcessingNeeded();

                MotionInfluenceLimiting();

                for (int i = 0; i < framesToSimulate; i++) // Simulating update frames
                {
                    SimulateTailMotionFrame(postProcesses);
                }

                // Updating root bone position
                TailSegments[_tc_startI].transform.position = TailSegments[_tc_startI].ProceduralPositionWeightBlended;
                TailSegments[_tc_startI].RefreshFinalPos(TailSegments[_tc_startI].ProceduralPositionWeightBlended);
                //TailSegments[_tc_startI].RefreshFinalLocalPos(TailSegments[_tc_startI].transform.localPosition);

                // Applying calculated coords to transforms
                if (_tc_startII > -1)
                {
                    TailSegment child = TailSegments[_tc_startII]; // Used in while() loops below
                    while (child != GhostChild)
                    {
                        // Calculate rotation
                        TailCalculations_SegmentRotation(child, child.LastKeyframeLocalPosition);

                        // Apply coords to segments
                        TailCalculations_ApplySegmentMotion(child);
                        child = child.ChildBone;
                    }
                }

                // If ghost child has transform let's apply motion too (change rotation of last bone)
                TailCalculations_SegmentRotation(GhostChild, GhostChild.LastKeyframeLocalPosition);
                GhostChild.ParentBone.transform.rotation = GhostChild.ParentBone.TrueTargetRotation;
                GhostChild.ParentBone.RefreshFinalRot(GhostChild.ParentBone.TrueTargetRotation);

                if (GhostChild.transform)
                {
                    GhostChild.RefreshFinalPos(GhostChild.transform.position);
                    GhostChild.RefreshFinalRot(GhostChild.transform.rotation);
                }
            }
            else // Skipping tail motion simulation and just applying coords computed lately
            // Executed only when using target UpdateRate
            {
                if (InterpolateRate)
                {
                    secPeriodDelta = rateDelta / 24f;
                    deltaForLerps  = secPeriodDelta; // Unify delta value not amplified -> 1f / rate

                    SimulateTailMotionFrame(PostProcessingNeeded());

                    if (_tc_startII > -1)
                    {
                        TailSegment child = TailSegments[_tc_startII];
                        while (child != GhostChild)
                        {
                            TailCalculations_SegmentRotation(child, child.LastKeyframeLocalPosition);
                            TailCalculations_ApplySegmentMotion(child);
                            child = child.ChildBone;
                        }
                    }

                    TailCalculations_SegmentRotation(GhostChild, GhostChild.LastKeyframeLocalPosition);
                    GhostChild.ParentBone.transform.rotation = GhostChild.ParentBone.TrueTargetRotation;
                    GhostChild.ParentBone.RefreshFinalRot(GhostChild.ParentBone.TrueTargetRotation);
                }
                else
                {
                    if (_tc_startI > -1)
                    {
                        TailSegment segment = TailSegments[_tc_startI];

                        while (segment != null)
                        {
                            if (segment.transform)
                            {
                                segment.transform.position = segment.LastFinalPosition;
                                segment.transform.rotation = segment.LastFinalRotation;
                            }
                            else
                            {
                                break;
                            }

                            segment = segment.ChildBone;
                        }
                    }
                    else
                    {
                    }
                }
            }
        }
    public override void Update()
    {
        base.Update();
        if (this.culled)
        {
            return;
        }
        for (int i = 0; i < this.danglers.Length; i++)
        {
            this.danglers[i].Update();
        }
        if (this.fish.Consious)
        {
            this.swim -= Custom.LerpMap(this.fish.swimSpeed, 1.6f, 5f, 0.0333333351f, 0.06666667f);
        }
        this.tail[0].connectedPoint     = new Vector2?(this.fish.bodyChunks[1].pos);
        this.wings[0, 0].connectedPoint = new Vector2?(this.fish.bodyChunks[0].pos);
        this.wings[1, 0].connectedPoint = new Vector2?(this.fish.bodyChunks[0].pos);
        Vector2 vector = Custom.DirVec(this.fish.bodyChunks[1].pos, this.fish.bodyChunks[0].pos);
        Vector2 a      = Custom.PerpendicularVector(vector);

        this.lastZRotation = this.zRotation;
        if (Mathf.Abs(vector.x) > 0.5f && this.fish.Consious)
        {
            this.zRotation = Vector2.Lerp(this.zRotation, new Vector2((vector.x <= 0f) ? 1f : -1f, 0f), 0.2f);
        }
        else
        {
            this.zRotation = Vector2.Lerp(this.zRotation, -vector, 0.5f);
        }
        this.zRotation = this.zRotation.normalized;
        if (this.fish.Consious)
        {
            float num = 1f - this.fish.bodyChunks[1].submersion;
            if (this.airEyes < num)
            {
                this.airEyes = Mathf.Min(this.airEyes + 0.1f, num);
            }
            else
            {
                this.airEyes = Mathf.Max(this.airEyes - 0.0333333351f, num);
            }
        }
        for (int i = 0; i < 2; i++)
        {
            this.flippers[i].Update();
            this.flippers[i].ConnectToPoint(this.fish.bodyChunks[1].pos, (this.flipperGraphWidth + 7f) * this.fish.iVars.flipperSize, false, 0f, this.fish.bodyChunks[1].vel, 0.3f, 0f);
            Vector2 vector2 = a * this.zRotation.y * ((i != 0) ? 1f : -1f);
            vector2 += new Vector2(0f, -0.5f) * Mathf.Abs(this.zRotation.x);
            vector2 += vector * this.fish.iVars.flipperOrientation * 1.5f;
            if (this.fish.Consious)
            {
                if (i == 0 == this.zRotation.x < 0f)
                {
                    vector2 += vector * Mathf.Sin(this.swim * 3.14159274f * 2f) * 0.3f * (1f - this.fish.jetActive);
                }
                else
                {
                    vector2 += vector * Mathf.Cos(this.swim * 3.14159274f * 2f) * 0.3f * (1f - this.fish.jetActive);
                }
                vector2 = Vector2.Lerp(vector2, -vector, this.fish.jetActive * this.fish.jetWater);
            }
            this.flippers[i].vel += (this.fish.bodyChunks[1].pos + vector2 * (this.flipperGraphWidth + 7f) * this.fish.iVars.flipperSize - this.flippers[i].pos) / ((!this.fish.Consious) ? 16f : 8f);
            if (this.fish.room.PointSubmerged(this.flippers[i].pos))
            {
                this.flippers[i].vel *= 0.9f;
            }
            else
            {
                GenericBodyPart genericBodyPart = this.flippers[i];
                genericBodyPart.vel.y = genericBodyPart.vel.y - 0.6f;
            }
            if (this.fish.iVars.whiskers > 0)
            {
                for (int j = 0; j < this.fish.iVars.whiskers; j++)
                {
                    this.whiskers[i, j].vel += this.whiskerDir(i, j, this.zRotation, vector) * this.whiskerProps[j, 2];
                    if (this.fish.room.PointSubmerged(this.whiskers[i, j].pos))
                    {
                        this.whiskers[i, j].vel *= 0.8f;
                    }
                    else
                    {
                        GenericBodyPart genericBodyPart2 = this.whiskers[i, j];
                        genericBodyPart2.vel.y = genericBodyPart2.vel.y - 0.6f;
                    }
                    this.whiskers[i, j].Update();
                    this.whiskers[i, j].ConnectToPoint(this.fish.bodyChunks[2].pos - vector * 5f + this.whiskerDir(i, j, this.zRotation, vector) * 5f, this.whiskerProps[j, 0], false, 0f, this.fish.bodyChunks[2].vel, 0f, 0f);
                }
            }

            for (int x = 0; x < 2; x++)
            {
                for (int k = 0; k < this.wings.GetLength(1); k++)
                {
                    Vector2 look = Custom.PerpendicularVector(Custom.DirVec(this.fish.bodyChunks[1].pos, this.fish.bodyChunks[0].pos));
                    if (x == 0)
                    {
                        look = -look;
                    }
                    float push = Custom.AimFromOneVectorToAnother(this.fish.bodyChunks[0].pos + look, this.fish.bodyChunks[0].pos);
                    this.wings[x, k].Update();
                    float num2 = Mathf.InverseLerp(0f, (float)(this.wings.GetLength(1) - 1), (float)k);
                    if (!Custom.DistLess(this.wings[x, k].pos, this.fish.bodyChunks[1].pos, 15f * (float)(k + 1)))
                    {
                        this.wings[x, k].pos = this.fish.bodyChunks[1].pos + Custom.DirVec(this.fish.bodyChunks[1].pos, this.wings[x, k].pos) * 15f * (float)(k + 1);
                    }
                    float num3 = this.fish.jetActive;
                    if (this.fish.room.PointSubmerged(this.wings[x, k].pos))
                    {
                        this.wings[x, k].vel *= 0.7f;
                        num3 = Mathf.Lerp(num3, 0f, 0.5f);
                    }
                    else
                    {
                        TailSegment wingSegment = this.wings[x, k];
                        wingSegment.vel.y = wingSegment.vel.y - 0.9f * Mathf.Pow((float)k / (float)(this.wings.GetLength(1) - 1), 3f);
                    }
                    this.wings[x, k].vel += a * Mathf.Sin((this.swim + (float)k / 5f) * 3.14159274f * 2f) * ((i != 0) ? -1f : 1f) * Mathf.Pow(1f - num2, 2f) * Custom.LerpMap(this.fish.swimSpeed, 1.6f, 5f, 8f, 16f) * (1f - num3);
                    this.wings[x, k].vel -= look * (0.2f * (1f - num3) + Mathf.Pow(Mathf.InverseLerp(0.5f, 0f, num2), 2f) * Mathf.Lerp(27f, 11f, num3));
                    float num4 = 30f + Mathf.Sin(Mathf.Pow(num2, 1f) * 3.14159274f * -2f) * -100f;
                    this.wings[x, k].vel          -= Custom.DegToVec(push + num4 * ((i != 0) ? -1f : 1f)) * Mathf.Lerp(12f, 6f, num2) * num3;
                    this.wings[x, k].connectionRad = Mathf.Lerp(10f, 0.5f, Mathf.Lerp(0f, num3, Mathf.Pow(num2, 0.2f))) * Mathf.Lerp(0.5f, 1.5f, this.fish.iVars.tentacleLength);
                    this.wings[x, k].rad           = Mathf.Lerp(this.TentacleContour(num2, k), Mathf.Lerp(8f, 2f, num2) * (0.5f + 0.5f * this.fish.jetWater), num3) * Mathf.Lerp(0.7f, 1.2f, this.fish.iVars.tentacleFatness);
                }
            }
            for (int k = 0; k < this.tail.Length; k++)
            {
                this.tail[k].Update();
                float num2 = Mathf.InverseLerp(0f, (float)(this.tail.Length - 1), (float)k);
                if (!Custom.DistLess(this.tail[k].pos, this.fish.bodyChunks[1].pos, 15f * (float)(k + 1)))
                {
                    this.tail[k].pos = this.fish.bodyChunks[1].pos + Custom.DirVec(this.fish.bodyChunks[1].pos, this.tail[k].pos) * 15f * (float)(k + 1);
                }
                float num3 = this.fish.jetActive;
                if (this.fish.room.PointSubmerged(this.tail[k].pos))
                {
                    this.tail[k].vel *= 0.7f;
                    num3              = Mathf.Lerp(num3, 0f, 0.5f);
                }
                else
                {
                    TailSegment tailSegment = this.tail[k];
                    tailSegment.vel.y = tailSegment.vel.y - 0.9f * Mathf.Pow((float)k / (float)(this.tail.Length - 1), 3f);
                }
                this.tail[k].vel += a * Mathf.Sin((this.swim + (float)k / 5f) * 3.14159274f * 2f) * ((i != 0) ? -1f : 1f) * Mathf.Pow(1f - num2, 2f) * Custom.LerpMap(this.fish.swimSpeed, 1.6f, 5f, 8f, 16f) * (1f - num3);
                this.tail[k].vel -= vector * (0.2f * (1f - num3) + Mathf.Pow(Mathf.InverseLerp(0.5f, 0f, num2), 2f) * Mathf.Lerp(27f, 11f, num3));
                float num4 = 30f + Mathf.Sin(Mathf.Pow(num2, 1f) * 3.14159274f * -2f) * -100f;
                this.tail[k].vel          -= Custom.DegToVec(Custom.AimFromOneVectorToAnother(this.fish.bodyChunks[1].pos, this.fish.bodyChunks[0].pos) + num4 * ((i != 0) ? -1f : 1f)) * Mathf.Lerp(12f, 6f, num2) * num3;
                this.tail[k].connectionRad = Mathf.Lerp(10f, 0.5f, Mathf.Lerp(0f, num3, Mathf.Pow(num2, 0.2f))) * Mathf.Lerp(0.5f, 1.5f, this.fish.iVars.tentacleLength);
                this.tail[k].rad           = Mathf.Lerp(this.TentacleContour(num2, k), Mathf.Lerp(8f, 2f, num2) * (0.5f + 0.5f * this.fish.jetWater), num3) * Mathf.Lerp(0.7f, 1.2f, this.fish.iVars.tentacleFatness);
            }
        }
    }
        /// <summary>
        /// Method to initialize component, to have more controll than waiting for Start() method, init can be executed before or after start, as programmer need it.
        /// </summary>
        protected virtual void Init()
        {
            if (initialized)
            {
                return;
            }


            // Checking if we have transform to create tail chain from
            if (_TransformsGhostChain == null || _TransformsGhostChain.Count == 0)
            {
                _TransformsGhostChain = new List <Transform>();
                GetGhostChain();
            }


            // Generating tail instances for procedural animation
            TailSegments = new List <TailSegment>();

            for (int i = 0; i < _TransformsGhostChain.Count; i++)
            {
                if (_TransformsGhostChain[i] == null)
                {
                    Debug.Log("[Tail Animator] Null bones in " + name + " !");
                    continue;
                }

                TailSegment b = new TailSegment(_TransformsGhostChain[i]);
                b.SetIndex(i, _TransformsGhostChain.Count);
                TailSegments.Add(b);
            }


            // Checking correctness
            if (TailSegments.Count == 0)
            {
                Debug.Log("[Tail Animator] Could not create tail bones chain in " + name + " !");
                return;
            }


            _TC_TailLength = 0f;
            _baseTransform = _TransformsGhostChain[0];

            //if (_baseTransform.parent)
            //    _baseTransform = _baseTransform.parent;
            //else
            //    IncludeParent = false;


            // Setting parent-child relation for tail logics
            for (int i = 0; i < TailSegments.Count; i++)
            {
                TailSegment current = TailSegments[i];
                TailSegment parent;

                #region Defining Parent Bones

                if (i == 0)
                {
                    if (current.transform.parent)
                    {
                        // Creating parent and setting safety parent
                        parent = new TailSegment(current.transform.parent);
                        parent.SetParentRef(new TailSegment(parent.transform.parent));
                    }
                    else
                    #region If first bone is parentless
                    {
                        parent = new TailSegment(current.transform);

                        Vector3 toStartDir;

                        if (_TransformsGhostChain.Count > 1)
                        {
                            toStartDir = _TransformsGhostChain[0].position - _TransformsGhostChain[1].position;
                            if (toStartDir.magnitude == 0)
                            {
                                toStartDir = transform.position - _TransformsGhostChain[1].position;
                            }
                        }
                        else
                        {
                            toStartDir = current.transform.position - _TransformsGhostChain[0].position;
                        }

                        if (toStartDir.magnitude == 0)
                        {
                            toStartDir = transform.position - _TransformsGhostChain[0].position;
                        }
                        if (toStartDir.magnitude == 0)
                        {
                            toStartDir = transform.forward;
                        }

                        parent.LocalOffset = parent.transform.InverseTransformPoint(parent.transform.position + toStartDir);
                        parent.SetParentRef(new TailSegment(current.transform));
                    }
                    #endregion

                    //current.InitialLocalRotation = Quaternion.Inverse(current.transform.localRotation);
                    GhostParent = parent;
                    GhostParent.Validate();
                    current.SetParentRef(GhostParent);
                }
                else // i != 0
                {
                    parent = TailSegments[i - 1];
                    // If bones are removed manually from chain we support custom length of bone undependent from transform parenting chain structure
                    current.ReInitializeLocalPosRot(parent.transform.InverseTransformPoint(current.transform.position), current.transform.localRotation);
                }


                #endregion


                #region Defining Last Child Bone

                if (i == TailSegments.Count - 1)
                {
                    Transform childT = null;
                    if (current.transform.childCount > 0)
                    {
                        childT = current.transform.GetChild(0);
                    }

                    GhostChild = new TailSegment(childT);

                    // Scale ref for ghosting object position offset
                    Vector3 scaleDir;

                    if (FEngineering.VIsZero(EndBoneJointOffset))
                    {
                        if (current.transform.parent)
                        {
                            scaleDir = current.transform.position - current.transform.parent.position;
                        }
                        else
                        if (current.transform.childCount > 0)
                        {
                            scaleDir = current.transform.GetChild(0).position - current.transform.position;
                        }
                        else
                        {
                            scaleDir = current.transform.TransformDirection(Vector3.forward) * 0.05f;
                        }
                    }
                    else
                    {
                        scaleDir = current.transform.TransformVector(EndBoneJointOffset);
                    }


                    GhostChild.ProceduralPosition = current.transform.position + scaleDir;
                    GhostChild.ProceduralPositionWeightBlended = GhostChild.ProceduralPosition;
                    GhostChild.PreviousPosition             = GhostChild.ProceduralPosition;
                    GhostChild.PosRefRotation               = Quaternion.identity;
                    GhostChild.PreviousPosReferenceRotation = Quaternion.identity;
                    GhostChild.ReInitializeLocalPosRot(current.transform.InverseTransformPoint(GhostChild.ProceduralPosition), Quaternion.identity);
                    GhostChild.RefreshFinalPos(GhostChild.ProceduralPosition);
                    GhostChild.RefreshFinalRot(GhostChild.PosRefRotation);
                    GhostChild.TrueTargetRotation = GhostChild.PosRefRotation;
                    current.TrueTargetRotation    = current.transform.rotation;

                    current.SetChildRef(GhostChild);
                    GhostChild.SetParentRef(current);
                }
                else
                {
                    current.SetChildRef(TailSegments[i + 1]);
                }

                #endregion


                current.SetParentRef(parent);

                _TC_TailLength += Vector3.Distance(current.ProceduralPosition, parent.ProceduralPosition);
            }


            // List with ghosts for curves etc.
            GhostParent.SetIndex(-1, TailSegments.Count);
            GhostChild.SetIndex(TailSegments.Count, TailSegments.Count);
            GhostParent.SetChildRef(TailSegments[0]);

            previousWorldPosition = BaseTransform.position;
            WavingRotationOffset  = Quaternion.identity;

            if (CollidersDataToCheck == null)
            {
                CollidersDataToCheck = new List <FImp_ColliderData_Base>();
            }

            DynamicAlwaysInclude = new List <Component>();
            if (UseCollision)
            {
                SetupSphereColliders();
            }

            // List instance for deflection feature
            if (_defl_source == null)
            {
                _defl_source = new List <TailSegment>();
            }

            Waving_Initialize();

            if (DetachChildren)
            {
                DetachChildrenTransforms();
            }

            initialized = true;

            if (TailSegments.Count == 1)
            {
                if (TailSegments[0].transform.parent == null)
                {
                    Debug.Log("[Tail Animator] Can't initialize one-bone length chain on bone which don't have any parent!");
                    Debug.LogError("[Tail Animator] Can't initialize one-bone length chain on bone which don't have any parent!");
                    TailAnimatorAmount = 0f;
                    initialized        = false;
                    return;
                }
            }

            if (UseWind)
            {
                TailAnimatorWind.Refresh(this);
            }

            if (PostProcessingNeeded())
            {
                if (!_pp_initialized)
                {
                    InitializePostProcessing();
                }
            }

            #region Prewarming tail to target state

            if (Prewarm)
            {
                ShapingParamsUpdate();
                ExpertParamsUpdate();

                Update();
                LateUpdate();

                justDelta      = rateDelta;
                secPeriodDelta = 1f;
                deltaForLerps  = secPeriodDelta;
                rateDelta      = 1f / 60f;

                CheckIfTailAnimatorShouldBeUpdated();

                if (updateTailAnimator)
                {
                    int loopCount = 60 + TailSegments.Count / 2;

                    for (int d = 0; d < loopCount; d++)
                    {
                        PreCalibrateBones();
                        LateUpdate();
                    }
                }
            }

            #endregion
        }
Example #21
0
        /// <summary>
        /// Tracks the tailsegments on the supplied image and returns
        /// the angles and distances of each segment from the tailstart
        /// </summary>
        /// <param name="image">The image on which to id the tail</param>
        /// <returns>NSegments number of TailPoints</returns>
        public TailSegment[] TrackTail(Image8 image)
        {
            lock (_regionLock)
            {
                //CURRENTLY ONLY DOWNWARD FACING TAILS ARE PROPERLY VERIFIED!!!
                //Generate background by morphology operation - 10 times a second or whenever our coordinates changed
                //in the default case where the tail is darker than the background, using closing operation otherwise opening
                if (_frameNumber % (_frameRate / 10) == 0 || !_bgValid)
                {
                    if (!_bgValid)
                    {
                        //if our regions changed, reblank our images!
                        ip.ippiSet_8u_C1R(0, _background.Image, _background.Stride, _background.Size);
                        ip.ippiSet_8u_C1R(0, _foreground.Image, _foreground.Stride, _foreground.Size);
                        ip.ippiSet_8u_C1R(0, _thresholded.Image, _thresholded.Stride, _thresholded.Size);
                    }
                    if (_lightOnDark)
                    {
                        BWImageProcessor.Open(image, _background, _calc1, _strel, _trackRegionOuter);
                    }
                    else
                    {
                        BWImageProcessor.Close(image, _background, _calc1, _strel, _trackRegionOuter);
                    }
                    _bgValid = true;
                }
                //Compute foreground
                IppHelper.IppCheckCall(cv.ippiAbsDiff_8u_C1R(_background[_trackRegionInner.TopLeft], _background.Stride, image[_trackRegionInner.TopLeft], image.Stride, _foreground[_trackRegionInner.TopLeft], _foreground.Stride, _trackRegionInner.Size));
                //Threshold
                BWImageProcessor.Im2Bw(_foreground, _thresholded, _trackRegionInner, _threshold);
                //Fill small holes
                BWImageProcessor.Close3x3(_thresholded, _thresholded, _calc1, _trackRegionOuter);
            }
            //Tracking concept: We track the angle of each segment end (TailStart+SegmentLength:TailEnd)
            //as the angular displacement from the previous segment end
            //To do this we define one full-circle with radius SegmentLength and an angle step corresponding
            //to ~1 Pixel. Then for each angle we pre-compute in InitializeScanPoints the corresponding x
            //and y offsets. From the full circle set we track -90 to +90 degrees around the angle of the
            //previous segment - for the initial segment that angle will be 0. For each segment we will return
            //the segment angle and its associated end-point coordinate
            var retval = new TailSegment[_nSegments];

            lock (_scanPointLock)
            {
                //The index of the absolute angle of the previous segment in our angle sweep array
                //determines which angles we sweep over for the next segment
                int prevAngleIndex   = _scanAngles.Length / 2;
                int nAnglesPerHalfPi = prevAngleIndex / 2;//this is the number of entries in the array that we have to walk to cover 90 degrees
                //we scan beginning with one segment length away from tail start and then walk
                //down the tail rather than using circles fixed arount the tailstart
                IppiPoint prevSegmentEnd = TailStart;

                //loop over tail segments
                for (int i = 0; i < _nSegments; i++)
                {
                    //loop over scan-points from -pi/2 to +pi/2 (i.e. nAnglesPerHalfPi) around previous segment angle
                    //interpreting the scan points as offsets around the previous tail segment
                    //end point
                    //then find tail angle of this segment
                    int pointsFound = 0;//the number of non-zero pixels identified
                    for (int j = -1 * nAnglesPerHalfPi; j < nAnglesPerHalfPi + 1; j++)
                    {
                        //Determine the index to scan - usually this will simply be "prevAngleIndex+j" however we
                        //have to loop around our angle array properly in case we screen more extreme angles
                        int currIndex = prevAngleIndex + j;
                        if (currIndex >= _scanAngles.Length)
                        {
                            currIndex = currIndex % _scanAngles.Length;
                        }
                        else if (currIndex < 0)
                        {
                            currIndex = currIndex + _scanAngles.Length;
                        }

                        //If current point is outside of the image, ignore it
                        IppiPoint pt = new IppiPoint(_coordinateOffsets[currIndex].x + prevSegmentEnd.x, _coordinateOffsets[currIndex].y + prevSegmentEnd.y);
                        if (pt.x < 0 || pt.y < 0 || pt.x >= _imageSize.width || pt.y >= _imageSize.height)
                        {
                            continue;
                        }
                        //if the value at the current point >0 we mark that angle as valid
                        //by storing the index in our anglestore
                        if (*_thresholded[pt] > 0)
                        {
                            _angleStore[pointsFound] = currIndex;
                            pointsFound++;
                        }
                    }
                    //find the median point in our angle store if we have more than 2 points stored
                    //the value in our angle store will directly give us the absolute screen angle of the segment
                    //as well as the coordinate offset which we can used together with the previous segment endpoint
                    //to compute the tail segment end coordinate - to get the delta angle we need to get the difference
                    //between the stored index and the previously stored index, prevAngleIndex
                    //after computing the appropriate return values we update prevAngleIndex with the index from the angle store
                    //and prevSegmentEnd with the returned coordinate of the current tail segment
                    double    deltaTailAngle;
                    IppiPoint coordinate;
                    int       pos;        //the index in the angle store that we determine to be the tail-center

                    if (pointsFound == 0) //we have lost the tail - no reason to keep tracking - fill remaining positions in array with NaNs for their angle
                    {
                        for (int k = i; k < _nSegments; k++)
                        {
                            deltaTailAngle = double.NaN;
                            coordinate     = new IppiPoint();
                            retval[k]      = new TailSegment(deltaTailAngle, coordinate);
                        }
                        break;
                    }
                    else if (pointsFound < 3)
                    {
                        pos = _angleStore[0];
                    }
                    else
                    {
                        //we want the angle at the median position of valid points
                        //we don't compute intermediate positions however (we should be able to afford this since our angle step is so small), so in case
                        //of an even number of points, the top of the lower half currently
                        //wins - since array indexing is zero based, we have to subtract 1
                        //from the computed median position
                        pos = _angleStore[(int)(Math.Ceiling(pointsFound / 2.0) - 1)];
                    }
                    coordinate     = new IppiPoint(prevSegmentEnd.x + _coordinateOffsets[pos].x, prevSegmentEnd.y + _coordinateOffsets[pos].y);
                    deltaTailAngle = (pos - prevAngleIndex) * _angleStep;
                    //the condition above of wrapping around the "angle circle":if (currIndex >= _scanAngles.Length)....
                    //results in one very large (close to +360 or -360) angle of opposite sign at the switch point
                    //however, since we usually only scan over offsets from +90 to -90 this case is easy to spot
                    //and remedy:
                    if (deltaTailAngle > 90)
                    {
                        deltaTailAngle = deltaTailAngle - 360;//this should create the appropriate tail angle btw. 0 and -90
                    }
                    else if (deltaTailAngle < -90)
                    {
                        deltaTailAngle = 360 + deltaTailAngle;//this should create the appropriate tail angle btw. 0 and +90
                    }
                    prevAngleIndex = pos;
                    prevSegmentEnd = coordinate;
                    retval[i]      = new TailSegment(deltaTailAngle, coordinate);
                }//loop over tail segments
            }
            _frameNumber++;
            return(retval);
        }
Example #22
0
    private static void PlayerGraphics_Update(On.PlayerGraphics.orig_Update orig, PlayerGraphics self)
    {
        //Super.Update()
        self.lastCulled = self.culled;
        self.culled     = self.ShouldBeCulled;
        if (!self.culled && self.lastCulled)
        {
            self.Reset();
        }

        //Update()
        self.lastMarkAlpha = self.markAlpha;
        if (!self.player.dead && self.player.room.game.session is StoryGameSession && (self.player.room.game.session as StoryGameSession).saveState.deathPersistentSaveData.theMark)
        {
            self.markAlpha = Custom.LerpAndTick(self.markAlpha, Mathf.Clamp(Mathf.InverseLerp(30f, 80f, (float)self.player.touchedNoInputCounter) - Random.value * Mathf.InverseLerp(80f, 30f, (float)self.player.touchedNoInputCounter), 0f, 1f) * self.markBaseAlpha, 0.1f, 0.033333335f);
        }
        else
        {
            self.markAlpha = 0f;
        }
        if (self.player.input[1].x != self.player.input[0].x || self.player.input[1].y != self.player.input[0].y)
        {
            self.flail = Mathf.Min(1f, self.flail + 0.33333334f);
        }
        else
        {
            self.flail = Mathf.Max(0f, self.flail - 0.0125f);
        }
        self.lastBreath = self.breath;
        if (!self.player.dead)
        {
            if (self.player.Sleeping)
            {
                self.breath += 0.0125f;
            }
            else
            {
                self.breath += 1f / Mathf.Lerp(60f, 15f, Mathf.Pow(self.player.aerobicLevel, 1.5f));
            }
        }
        if (self.lightSource != null)
        {
            self.lightSource.stayAlive = true;
            self.lightSource.setPos    = new Vector2?(self.player.mainBodyChunk.pos);
            if (self.lightSource.slatedForDeletetion || self.player.room.Darkness(self.player.mainBodyChunk.pos) == 0f)
            {
                self.lightSource = null;
            }
        }
        else if (self.player.room.Darkness(self.player.mainBodyChunk.pos) > 0f && self.player.glowing)
        {
            self.lightSource = new LightSource(self.player.mainBodyChunk.pos, false, Color.Lerp(new Color(1f, 1f, 1f), PlayerGraphics.SlugcatColor(self.player.playerState.slugcatCharacter), 0.5f), self.player);
            self.lightSource.requireUpKeep = true;
            self.lightSource.setRad        = new float?(300f);
            self.lightSource.setAlpha      = new float?(1f);
            self.player.room.AddObject(self.lightSource);
        }
        if (self.malnourished > 0f && !self.player.Malnourished)
        {
            self.malnourished = Mathf.Max(0f, self.malnourished - 0.005f);
        }
        if (self.player.bodyMode == Player.BodyModeIndex.Stand && self.player.input[0].x != 0)
        {
            self.spearDir = Mathf.Clamp(self.spearDir + (float)self.player.input[0].x * 0.1f, -1f, 1f);
        }
        else if (self.spearDir < 0f)
        {
            self.spearDir = Mathf.Min(self.spearDir + 0.05f, 0f);
        }
        else if (self.spearDir > 0f)
        {
            self.spearDir = Mathf.Max(self.spearDir - 0.05f, 0f);
        }
        if (self.player.room.world.rainCycle.RainApproaching < 1f && Random.value > self.player.room.world.rainCycle.RainApproaching && Random.value < 0.009803922f && (self.player.room.roomSettings.DangerType == RoomRain.DangerType.Rain || self.player.room.roomSettings.DangerType == RoomRain.DangerType.FloodAndRain))
        {
            self.objectLooker.LookAtPoint(new Vector2(self.player.room.PixelWidth * Random.value, self.player.room.PixelHeight + 100f), (1f - self.player.room.world.rainCycle.RainApproaching) * 0.6f);
        }
        float num = 0f;

        if (self.player.Consious && self.objectLooker.currentMostInteresting != null && self.objectLooker.currentMostInteresting is Creature)
        {
            CreatureTemplate.Relationship relationship = self.player.abstractCreature.creatureTemplate.CreatureRelationship((self.objectLooker.currentMostInteresting as Creature).abstractCreature.creatureTemplate);
            if (relationship.type == CreatureTemplate.Relationship.Type.Afraid && !(self.objectLooker.currentMostInteresting as Creature).dead)
            {
                float from = Mathf.Lerp(40f, 250f, relationship.intensity);
                num = Mathf.InverseLerp(from, 10f, Vector2.Distance(self.player.mainBodyChunk.pos, self.objectLooker.mostInterestingLookPoint) * ((!self.player.room.VisualContact(self.player.mainBodyChunk.pos, self.objectLooker.mostInterestingLookPoint)) ? 1.5f : 1f));
                if ((self.objectLooker.currentMostInteresting as Creature).abstractCreature.abstractAI != null && (self.objectLooker.currentMostInteresting as Creature).abstractCreature.abstractAI.RealAI != null)
                {
                    num *= (self.objectLooker.currentMostInteresting as Creature).abstractCreature.abstractAI.RealAI.CurrentPlayerAggression(self.player.abstractCreature);
                }
            }
        }
        if (!self.player.Consious)
        {
            self.objectLooker.LookAtNothing();
            self.blink = 10;
        }
        if (self.DEBUGLABELS != null)
        {
            self.DEBUGLABELS[0].label.text = self.player.bodyMode.ToString() + " " + self.player.animation.ToString();
            self.DEBUGLABELS[1].label.text = string.Concat(new object[]
            {
                "XPOS: ",
                self.player.mainBodyChunk.pos.x,
                " YPOS: ",
                self.player.mainBodyChunk.pos.y
            });
            self.DEBUGLABELS[2].label.text = string.Concat(new object[]
            {
                "XPOS: ",
                self.player.bodyChunks[1].pos.x,
                " YPOS: ",
                self.player.bodyChunks[1].pos.y
            });
        }
        for (int i = 0; i < self.owner.bodyChunks.Length; i++)
        {
            self.drawPositions[i, 1] = self.drawPositions[i, 0];
        }
        self.drawPositions[0, 0] = self.owner.bodyChunks[0].pos;
        self.drawPositions[1, 0] = self.owner.bodyChunks[1].pos;
        int   num2 = 0;
        bool  flag = false;
        float num3 = 1f;

        switch (self.player.bodyMode)
        {
        case Player.BodyModeIndex.Default:
            if (self.player.animation == Player.AnimationIndex.AntlerClimb)
            {
                num2 = 2;
            }
            else if (self.player.animation == Player.AnimationIndex.LedgeGrab)
            {
                self.legsDirection.y        = self.legsDirection.y - 1f;
                self.drawPositions[0, 0].x -= (float)self.player.flipDirection * 5f;
            }
            else
            {
                num3 = 0f;
            }
            break;

        case Player.BodyModeIndex.Crawl:
        {
            num2 = 1;
            float num4 = Mathf.Sin((float)self.player.animationFrame / 21f * 2f * 3.1415927f);
            float num5 = Mathf.Cos((float)self.player.animationFrame / 14f * 2f * 3.1415927f);
            float num6 = (self.player.superLaunchJump <= 19) ? 1f : 0f;
            self.drawPositions[0, 0].x += num5 * (float)self.player.flipDirection * 2f;
            self.drawPositions[0, 0].y -= num4 * -1.5f - 3f;
            GenericBodyPart genericBodyPart = self.head;
            genericBodyPart.vel.y = genericBodyPart.vel.y - (num4 * -0.5f - 0.5f);
            GenericBodyPart genericBodyPart2 = self.head;
            genericBodyPart2.vel.x      = genericBodyPart2.vel.x + ((self.owner.bodyChunks[0].pos.x >= self.owner.bodyChunks[1].pos.x) ? 1f : -1f);
            self.drawPositions[1, 0].x += -3f * num4 * (float)self.player.flipDirection;
            self.drawPositions[1, 0].y -= num5 * 1.5f - 7f + 3f * num6;
            break;
        }

        case Player.BodyModeIndex.Stand:
            self.drawPositions[0, 0].x += (float)self.player.flipDirection * 6f * Mathf.Clamp(Mathf.Abs(self.owner.bodyChunks[1].vel.x) - 0.2f, 0f, 1f);
            self.drawPositions[0, 0].y += Mathf.Cos((float)self.player.animationFrame / 6f * 2f * 3.1415927f) * 2f;
            self.drawPositions[1, 0].x -= (float)self.player.flipDirection * (1.5f - (float)self.player.animationFrame / 6f);
            self.drawPositions[1, 0].y += 2f + Mathf.Sin((float)self.player.animationFrame / 6f * 2f * 3.1415927f) * 4f;
            flag = (Mathf.Abs(self.owner.bodyChunks[0].vel.x) > 2f && Mathf.Abs(self.owner.bodyChunks[1].vel.x) > 2f);
            num3 = 1f - Mathf.Clamp((Mathf.Abs(self.owner.bodyChunks[1].vel.x) - 1f) * 0.5f, 0f, 1f);
            break;

        case Player.BodyModeIndex.WallClimb:
        {
            num2 = 1;
            self.legsDirection.y        = self.legsDirection.y - 1f;
            self.drawPositions[0, 0].y += 2f;
            self.drawPositions[0, 0].x -= (float)self.player.flipDirection * ((self.owner.bodyChunks[1].ContactPoint.y >= 0) ? 5f : 3f);
            GenericBodyPart genericBodyPart3 = self.head;
            genericBodyPart3.vel.y = genericBodyPart3.vel.y - (float)self.player.flipDirection * 5f;
            break;
        }

        case Player.BodyModeIndex.ClimbingOnBeam:
            num2 = 2;
            switch (self.player.animation)
            {
            case Player.AnimationIndex.GetUpOnBeam:
                self.disbalanceAmount = 70f;
                break;

            case Player.AnimationIndex.StandOnBeam:
                num2 = 0;
                self.drawPositions[1, 0].y += 3f;
                flag = (Mathf.Abs(self.owner.bodyChunks[0].vel.x) > 2f && Mathf.Abs(self.owner.bodyChunks[1].vel.x) > 2f);
                num3 = 1f - Mathf.Clamp((Mathf.Abs(self.owner.bodyChunks[1].vel.x) - 1f) * 0.3f, 0f, 1f);
                if (flag)
                {
                    TailSegment tailSegment = self.tail[0];
                    tailSegment.vel.x = tailSegment.vel.x - self.owner.bodyChunks[0].vel.x * 2f;
                    TailSegment tailSegment2 = self.tail[0];
                    tailSegment2.vel.y = tailSegment2.vel.y + 1.5f;
                    TailSegment tailSegment3 = self.tail[1];
                    tailSegment3.vel.x = tailSegment3.vel.x - self.owner.bodyChunks[0].vel.x * 0.2f;
                    TailSegment tailSegment4 = self.tail[1];
                    tailSegment4.vel.y = tailSegment4.vel.y + 0.5f;
                }
                break;

            case Player.AnimationIndex.ClimbOnBeam:
                self.drawPositions[0, 0].x += (float)self.player.flipDirection * 2.5f + (float)self.player.flipDirection * 0.5f * Mathf.Sin((float)self.player.animationFrame / 20f * 3.1415927f * 2f);
                self.drawPositions[1, 0].x += (float)self.player.flipDirection * 2.5f * Mathf.Cos((float)self.player.animationFrame / 20f * 3.1415927f * 2f);
                break;

            case Player.AnimationIndex.GetUpToBeamTip:
                self.disbalanceAmount = 120f;
                break;
            }
            break;

        case Player.BodyModeIndex.Swimming:
            if (self.player.animation == Player.AnimationIndex.DeepSwim || self.player.input[0].x != 0)
            {
                self.drawPositions[1, 0] += Custom.PerpendicularVector(Custom.DirVec(self.player.bodyChunks[0].pos, self.player.bodyChunks[1].pos)) * Mathf.Sin(self.player.swimCycle * 2f * 3.1415927f) * 5f;
            }
            break;

        case Player.BodyModeIndex.ZeroG:
            self.disbalanceAmount = Mathf.Max(self.disbalanceAmount, 70f * Mathf.InverseLerp(0.8f, 1f, self.flail));
            break;
        }
        switch (self.player.animation)
        {
        case Player.AnimationIndex.CorridorTurn:
            self.drawPositions[0, 0] += Custom.DegToVec(Random.value * 360f) * 3f * Random.value;
            self.drawPositions[1, 0] += Custom.DegToVec(Random.value * 360f) * 2f * Random.value;
            self.blink = 5;
            break;

        case Player.AnimationIndex.Roll:
        case Player.AnimationIndex.Flip:
        {
            float   num7 = 6f;
            Vector2 a    = Custom.DirVec(self.player.bodyChunks[0].pos, self.player.bodyChunks[1].pos);
            for (int j = 0; j < self.tail.Length; j++)
            {
                self.tail[j].vel += a * num7;
                num7             /= 1.7f;
            }
            break;
        }
        }
        if (self.player.bodyMode == Player.BodyModeIndex.Default && self.player.animation == Player.AnimationIndex.None && self.owner.bodyChunks[0].ContactPoint.x == 0 && self.owner.bodyChunks[0].ContactPoint.y == 0 && self.owner.bodyChunks[1].ContactPoint.x == 0 && self.owner.bodyChunks[1].ContactPoint.y == 0)
        {
            self.airborneCounter += self.owner.bodyChunks[0].vel.magnitude;
        }
        else
        {
            self.airborneCounter = 0f;
        }
        if (self.player.bodyMode == Player.BodyModeIndex.ClimbingOnBeam && (self.player.animation == Player.AnimationIndex.BeamTip || self.player.animation == Player.AnimationIndex.StandOnBeam))
        {
            if (Mathf.Abs(self.owner.bodyChunks[0].vel.x) > 2f)
            {
                self.disbalanceAmount += ((self.player.animation != Player.AnimationIndex.BeamTip) ? 3f : 17f);
            }
            else
            {
                self.disbalanceAmount -= 1f;
            }
            self.disbalanceAmount = Mathf.Clamp(self.disbalanceAmount, 0f, 120f);
            self.balanceCounter  += 1f + self.disbalanceAmount / 40f * (1f + Random.value);
            if (self.balanceCounter > 300f)
            {
                self.balanceCounter -= 300f;
            }
            float num8 = Mathf.Sin(self.balanceCounter / 300f * 3.1415927f * 2f) / (Mathf.Abs(self.owner.bodyChunks[1].vel.x) + 1f);
            self.drawPositions[0, 0].x += num8 * (self.disbalanceAmount + 20f) * 0.08f;
            self.drawPositions[0, 0].y += num8 * self.disbalanceAmount * 0.02f;
            TailSegment tailSegment5 = self.tail[0];
            tailSegment5.vel.x = tailSegment5.vel.x + num8 * (self.disbalanceAmount + 20f) * 0.1f;
            TailSegment tailSegment6 = self.tail[1];
            tailSegment6.vel.x = tailSegment6.vel.x + num8 * (self.disbalanceAmount + 20f) * 0.04f;
        }
        if (self.player.bodyMode == Player.BodyModeIndex.ZeroG)
        {
            self.disbalanceAmount -= 1f;
            self.disbalanceAmount  = Mathf.Clamp(self.disbalanceAmount, 0f, 120f);
            self.balanceCounter   += 1f + self.disbalanceAmount / 40f * (1f + Random.value);
            if (self.balanceCounter > 300f)
            {
                self.balanceCounter -= 300f;
            }
            float   d      = Mathf.Sin(self.balanceCounter / 300f * 3.1415927f * 2f);
            Vector2 vector = Custom.DirVec(self.player.bodyChunks[1].pos, self.player.mainBodyChunk.pos);
            Vector2 a2     = Custom.PerpendicularVector(vector);
            self.drawPositions[0, 0] += a2 * d * (self.disbalanceAmount + 20f) * 0.08f;
            self.tail[0].vel         -= a2 * d * (self.disbalanceAmount + 20f) * 0.1f + vector * self.disbalanceAmount * 0.1f;
            self.tail[1].vel         -= a2 * d * (self.disbalanceAmount + 20f) * 0.04f + vector * self.disbalanceAmount * 0.04f;
        }
        if (self.player.Consious && self.player.standing && num > 0.5f)
        {
            self.drawPositions[0, 0] += Custom.DirVec(self.objectLooker.mostInterestingLookPoint, self.player.bodyChunks[0].pos) * 3.4f * Mathf.InverseLerp(0.5f, 1f, num);
            self.head.vel            += Custom.DirVec(self.objectLooker.mostInterestingLookPoint, self.head.pos) * 1.4f * Mathf.InverseLerp(0.5f, 1f, num);
        }
        if (num > 0f)
        {
            self.tail[0].vel        += Custom.DirVec(self.objectLooker.mostInterestingLookPoint, self.drawPositions[1, 0]) * 5f * num;
            self.tail[1].vel        += Custom.DirVec(self.objectLooker.mostInterestingLookPoint, self.drawPositions[1, 0]) * 3f * num;
            self.player.aerobicLevel = Mathf.Max(self.player.aerobicLevel, Mathf.InverseLerp(0.5f, 1f, num) * 0.9f);
        }
        Vector2 vector2 = self.owner.bodyChunks[0].pos;

        if (flag)
        {
            vector2    = self.owner.bodyChunks[1].pos;
            vector2.y -= 4f;
            vector2.x += (float)self.player.flipDirection * 16f * Mathf.Clamp(Mathf.Abs(self.owner.bodyChunks[1].vel.x) - 0.2f, 0f, 1f);
        }
        Vector2 pos  = self.owner.bodyChunks[1].pos;
        float   num9 = 28f;

        self.tail[0].connectedPoint = new Vector2?(self.drawPositions[1, 0]);
        for (int k = 0; k < self.tail.Length; k++)
        {
            self.tail[k].Update();
            self.tail[k].vel *= Mathf.Lerp(0.75f, 0.95f, num3 * (1f - self.owner.bodyChunks[1].submersion));
            TailSegment tailSegment7 = self.tail[k];
            tailSegment7.vel.y = tailSegment7.vel.y - Mathf.Lerp(0.1f, 0.5f, num3) * (1f - self.owner.bodyChunks[1].submersion) * self.owner.room.gravity;
            num3 = (num3 * 10f + 1f) / 11f;
            if (!Custom.DistLess(self.tail[k].pos, self.owner.bodyChunks[1].pos, 9f * (float)(k + 1)))
            {
                self.tail[k].pos = self.owner.bodyChunks[1].pos + Custom.DirVec(self.owner.bodyChunks[1].pos, self.tail[k].pos) * 9f * (float)(k + 1);
            }
            self.tail[k].vel += Custom.DirVec(vector2, self.tail[k].pos) * num9 / Vector2.Distance(vector2, self.tail[k].pos);
            num9             *= 0.5f;
            vector2           = pos;
            pos = self.tail[k].pos;
        }
        if (self.player.swallowAndRegurgitateCounter > 15 && self.player.swallowAndRegurgitateCounter % 10 == 0)
        {
            self.blink = Math.Max(self.blink, Random.Range(-5, 8));
        }
        if (self.swallowing > 0)
        {
            self.swallowing--;
            self.blink = 5;
            self.drawPositions[0, 0] = Vector2.Lerp(self.drawPositions[0, 0], self.drawPositions[1, 0], 0.4f * Mathf.Sin((float)self.swallowing / 12f * 3.1415927f));
        }
        else if ((self.player.objectInStomach != null || KarmaAppetite_ExtraInventory.HasSomethingInInventory(self.player)) && self.player.swallowAndRegurgitateCounter > 0)         //Head movement on spit
        {
            if (self.player.swallowAndRegurgitateCounter > 30)
            {
                self.blink = 5;
            }
            float num10 = Mathf.InverseLerp(0f, 110f, (float)self.player.swallowAndRegurgitateCounter);
            float num11 = (float)self.player.swallowAndRegurgitateCounter / Mathf.Lerp(30f, 15f, num10);
            if (self.player.standing)
            {
                self.drawPositions[0, 0].y += Mathf.Sin(num11 * 3.1415927f * 2f) * num10 * 2f;
                self.drawPositions[1, 0].y += -Mathf.Sin((num11 + 0.2f) * 3.1415927f * 2f) * num10 * 3f;
            }
            else
            {
                self.drawPositions[0, 0].y += Mathf.Sin(num11 * 3.1415927f * 2f) * num10 * 3f;
                self.drawPositions[0, 0].x += Mathf.Cos(num11 * 3.1415927f * 2f) * num10 * 1f;
                self.drawPositions[1, 0].y += Mathf.Sin((num11 + 0.2f) * 3.1415927f * 2f) * num10 * 2f;
                self.drawPositions[1, 0].x += -Mathf.Cos(num11 * 3.1415927f * 2f) * num10 * 3f;
            }
        }
        self.blink--;
        if (self.blink < -Random.Range(2, 1800))
        {
            self.blink = Random.Range(3, Random.Range(3, 10));
        }
        if (!self.player.dead)
        {
            if (self.player.exhausted)
            {
                if (self.player.aerobicLevel > 0.8f)
                {
                    self.blink = Math.Max(self.blink, 1);
                }
                else if (Random.value < 0.02f)
                {
                    self.blink = Math.Max(self.blink, Random.Range(10, 20));
                }
            }
            if (self.player.lungsExhausted || self.player.exhausted)
            {
                self.objectLooker.LookAtNothing();
                GenericBodyPart genericBodyPart4 = self.head;
                genericBodyPart4.vel.y      = genericBodyPart4.vel.y + Mathf.Sin(self.player.swimCycle * 3.1415927f * 2f) * ((!self.player.lungsExhausted) ? 0.25f : 1f);
                self.drawPositions[0, 0].y += Mathf.Sin(self.player.swimCycle * 3.1415927f * 2f) * ((!self.player.lungsExhausted) ? 0.75f : 2.5f);
                self.blink = 1;
            }
        }
        if (Random.value < 0.1f)
        {
            self.objectLooker.Update();
        }
        if (Random.value < 0.0025f)
        {
            self.objectLooker.LookAtNothing();
        }
        self.lastLookDir = self.lookDirection;
        if (self.player.Consious && self.objectLooker.looking)
        {
            self.lookDirection = Custom.DirVec(self.head.pos, self.objectLooker.mostInterestingLookPoint);
        }
        else
        {
            self.lookDirection *= 0f;
        }
        if (num > 0.86f)
        {
            self.blink          = 5;
            self.lookDirection *= -1f;
        }
        if (self.player.grasps[0] != null && self.player.grasps[0].grabbed is JokeRifle)
        {
            self.lookDirection = (self.player.grasps[0].grabbed as JokeRifle).aimDir;
        }
        if (self.player.standing)
        {
            if (self.player.input[0].x == 0)
            {
                self.head.vel -= self.lookDirection * 0.5f;
            }
            self.drawPositions[0, 0] -= self.lookDirection * 2f;
        }
        else
        {
            self.head.vel += self.lookDirection;
        }
        Vector2 b = Custom.DirVec(self.drawPositions[1, 0], self.drawPositions[0, 0]) * 3f;

        if (self.player.bodyMode == Player.BodyModeIndex.Crawl)
        {
            b.x *= 2.5f;
        }
        else if (self.player.bodyMode == Player.BodyModeIndex.CorridorClimb && b.y < 0f)
        {
            b.y *= 2f;
        }
        self.head.Update();
        self.head.ConnectToPoint(Vector2.Lerp(self.drawPositions[0, 0], self.drawPositions[1, 0], 0.2f) + b, (self.player.animation != Player.AnimationIndex.HangFromBeam) ? 3f : 0f, false, 0.2f, self.owner.bodyChunks[0].vel, 0.7f, 0.1f);
        self.legs.Update();
        if (self.player.bodyMode == Player.BodyModeIndex.CorridorClimb)
        {
            self.legs.ConnectToPoint(self.owner.bodyChunks[1].pos + Custom.DirVec(self.owner.bodyChunks[0].pos, self.owner.bodyChunks[1].pos) * 4f, 2f, false, 0.25f, self.owner.bodyChunks[1].vel, 0.5f, 0.1f);
            int num12 = Mathf.RoundToInt((270f - Custom.AimFromOneVectorToAnother(self.owner.bodyChunks[1].pos, self.owner.bodyChunks[0].pos)) / 45f);
            int num13 = 10;
            int num14 = 0;
            for (int l = 0; l < 4; l++)
            {
                if (self.owner.room.GetTile(self.owner.room.GetTilePosition(self.owner.bodyChunks[1].pos) + Custom.eightDirections[(l + num12 + 10) % 8]).Terrain == Room.Tile.TerrainType.Solid && self.owner.room.GetTile(self.owner.room.GetTilePosition(self.owner.bodyChunks[1].pos) + Custom.eightDirections[(l + num12 + 14) % 8]).Terrain == Room.Tile.TerrainType.Solid)
                {
                    int num15 = 0;
                    if (l == 1)
                    {
                        num15 = ((self.player.flipDirection != -1) ? 2 : 1);
                    }
                    else if (l == 3)
                    {
                        num15 = ((self.player.flipDirection != 1) ? 2 : 1);
                    }
                    else if (l == 2)
                    {
                        num15 = 3;
                    }
                    if (num15 < num13)
                    {
                        num13 = num15;
                        switch (l)
                        {
                        case 0:
                            num14 = 0;
                            break;

                        case 1:
                            num14 = 45;
                            break;

                        case 2:
                            num14 = ((self.player.flipDirection != -1) ? 90 : -90);
                            break;

                        case 3:
                            num14 = -45;
                            break;
                        }
                    }
                }
            }
            self.legsDirection += Custom.DegToVec(Custom.AimFromOneVectorToAnother(self.owner.bodyChunks[0].pos, self.owner.bodyChunks[1].pos) + (float)num14);
        }
        else if (self.owner.bodyChunks[1].ContactPoint.y == -1 || self.player.animation == Player.AnimationIndex.StandOnBeam)
        {
            self.legs.ConnectToPoint(self.owner.bodyChunks[1].pos + new Vector2(self.legsDirection.x * 8f, 1f), 5f, false, 0.25f, new Vector2(self.owner.bodyChunks[1].vel.x, -10f), 0.5f, 0.1f);
            self.legsDirection.x = self.legsDirection.x - (float)self.owner.bodyChunks[1].onSlope;
            self.legsDirection.y = self.legsDirection.y - 1f;
        }
        else if (self.player.animation == Player.AnimationIndex.BeamTip)
        {
            self.legs.ConnectToPoint(self.owner.bodyChunks[1].pos + new Vector2(0f, -8f), 0f, false, 0.25f, new Vector2(0f, -10f), 0.5f, 0.1f);
            self.legsDirection += Custom.DirVec(self.drawPositions[0, 0], self.owner.room.MiddleOfTile(self.owner.bodyChunks[1].pos) + new Vector2(0f, -10f));
        }
        else if (self.player.animation == Player.AnimationIndex.ClimbOnBeam)
        {
            Vector2 b2 = new Vector2((float)(-(float)self.player.flipDirection) * (5f - Mathf.Sin((float)self.player.animationFrame / 20f * 3.1415927f * 2f)), -16f - 5f * Mathf.Cos((float)self.player.animationFrame / 20f * 3.1415927f * 2f));
            self.legs.ConnectToPoint(self.owner.bodyChunks[0].pos + b2, 0f, false, 0.25f, new Vector2(0f, 0f), 0.5f, 0.1f);
            self.legsDirection.y = self.legsDirection.y - 1f;
        }
        else if (self.player.animation == Player.AnimationIndex.ZeroGSwim || self.player.animation == Player.AnimationIndex.ZeroGPoleGrab)
        {
            self.legs.ConnectToPoint(self.owner.bodyChunks[1].pos + Custom.DirVec(self.owner.bodyChunks[0].pos, self.owner.bodyChunks[1].pos) * 4f, 4f, false, 0f, self.owner.bodyChunks[1].vel, 0.2f, 0f);
            self.legsDirection = Custom.DirVec(self.owner.bodyChunks[0].pos, self.owner.bodyChunks[1].pos);
            self.legs.vel     += self.legsDirection * 0.2f;
        }
        else
        {
            self.legs.ConnectToPoint(self.owner.bodyChunks[1].pos + new Vector2(self.legsDirection.x * 8f, (self.player.animation != Player.AnimationIndex.HangFromBeam) ? -2f : -5f), 4f, false, 0.25f, new Vector2(self.owner.bodyChunks[1].vel.x, -10f), 0.5f, 0.1f);
            self.legsDirection  += self.owner.bodyChunks[1].vel * 0.01f;
            self.legsDirection.y = self.legsDirection.y - 0.05f;
        }
        self.legsDirection.Normalize();
        if (self.player.Consious)
        {
            if (self.throwCounter > 0 && self.thrownObject != null)
            {
                self.hands[self.handEngagedInThrowing].reachingForObject = true;
                self.hands[self.handEngagedInThrowing].absoluteHuntPos   = self.thrownObject.firstChunk.pos;
                if (Custom.DistLess(self.hands[self.handEngagedInThrowing].pos, self.thrownObject.firstChunk.pos, 40f))
                {
                    self.hands[self.handEngagedInThrowing].pos = self.thrownObject.firstChunk.pos;
                }
                else
                {
                    self.hands[self.handEngagedInThrowing].vel += Custom.DirVec(self.hands[self.handEngagedInThrowing].pos, self.thrownObject.firstChunk.pos) * 6f;
                }
                self.hands[1 - self.handEngagedInThrowing].vel -= Custom.DirVec(self.hands[self.handEngagedInThrowing].pos, self.thrownObject.firstChunk.pos) * 3f;
                self.throwCounter--;
            }
            else if (self.player.handOnExternalFoodSource != null)
            {
                int num16 = (self.player.handOnExternalFoodSource.Value.x >= self.player.mainBodyChunk.pos.x) ? 1 : 0;
                self.hands[num16].reachingForObject = true;
                if (self.player.eatExternalFoodSourceCounter < 3)
                {
                    self.hands[num16].absoluteHuntPos = self.head.pos;
                    self.blink = Math.Max(self.blink, 3);
                }
                else
                {
                    self.hands[num16].absoluteHuntPos = self.player.handOnExternalFoodSource.Value;
                }
                self.drawPositions[0, 0] += Custom.DirVec(self.drawPositions[0, 0], self.player.handOnExternalFoodSource.Value) * 5f;
                self.head.vel            += Custom.DirVec(self.drawPositions[0, 0], self.player.handOnExternalFoodSource.Value) * 2f;
            }
            else if ((self.player.grasps[0] != null && self.player.grasps[0].grabbed is TubeWorm) || (self.player.grasps[1] != null && self.player.grasps[1].grabbed is TubeWorm))
            {
                for (int m = 0; m < self.player.grasps.Length; m++)
                {
                    if (self.player.grasps[m] != null && self.player.grasps[m].grabbed is TubeWorm)
                    {
                        self.hands[m].mode            = Limb.Mode.HuntRelativePosition;
                        self.hands[m].relativeHuntPos = new Vector2(5f * ((m != 0) ? 1f : -1f), -10f);
                    }
                }
            }
            else if (self.player.spearOnBack != null && self.player.spearOnBack.counter > 5)
            {
                int num17 = -1;
                int num18 = 0;
                while (num18 < 2 && num17 == -1)
                {
                    if ((self.player.spearOnBack.HasASpear && self.player.grasps[num18] == null) || (!self.player.spearOnBack.HasASpear && self.player.grasps[num18] != null && self.player.grasps[num18].grabbed is Spear))
                    {
                        num17 = num18;
                    }
                    num18++;
                }
                if (num17 > -1)
                {
                    if (self.player.grasps[num17] != null && self.player.grasps[num17].grabbed is Weapon)
                    {
                        (self.player.grasps[num17].grabbed as Weapon).ChangeOverlap(false);
                    }
                    self.hands[num17].reachingForObject = true;
                    self.hands[num17].mode = Limb.Mode.HuntRelativePosition;
                    if (self.player.spearOnBack.HasASpear)
                    {
                        self.hands[num17].relativeHuntPos = Vector3.Slerp(new Vector2(((num17 != 0) ? 1f : -1f) * 20f, -30f) * Mathf.Sin(Mathf.InverseLerp(9f, 20f, (float)self.player.spearOnBack.counter) * 3.1415927f), new Vector2(0f, 1f), Mathf.InverseLerp(9f, 20f, (float)self.player.spearOnBack.counter));
                    }
                    else
                    {
                        self.hands[num17].relativeHuntPos = Vector3.Slerp(new Vector2(((num17 != 0) ? 1f : -1f) * 30f, -20f) * Mathf.Lerp(1f, 0.2f, Mathf.Abs(self.player.spearOnBack.flip)), new Vector2(1f, 1f), Mathf.InverseLerp(14f, 20f, (float)self.player.spearOnBack.counter));
                    }
                    self.drawPositions[0, 0] += Custom.DirVec(self.hands[num17].absoluteHuntPos, self.drawPositions[0, 0]) * 0.7f;
                    self.head.vel            += Custom.DirVec(self.hands[num17].absoluteHuntPos, self.head.pos) * 1.5f;
                }
            }
            else if (self.player.FoodInStomach < self.player.MaxFoodInStomach && self.objectLooker.currentMostInteresting != null && num2 < 2 && ((self.objectLooker.currentMostInteresting is Fly && (self.objectLooker.currentMostInteresting as Fly).PlayerAutoGrabable) || num > 0.8f) && Custom.DistLess(self.player.mainBodyChunk.pos, self.objectLooker.mostInterestingLookPoint, 80f) && self.player.room.VisualContact(self.player.mainBodyChunk.pos, self.objectLooker.mostInterestingLookPoint))
            {
                int num19 = -1;
                for (int n = 0; n < 2; n++)
                {
                    if (self.player.grasps[n] == null && self.hands[1 - n].reachedSnapPosition)
                    {
                        num19 = n;
                    }
                }
                if (self.objectLooker.currentMostInteresting is Fly && (self.objectLooker.currentMostInteresting as Fly).PlayerAutoGrabable && self.player.input[0].x != 0 && self.objectLooker.currentMostInteresting.bodyChunks[0].pos.x < self.player.mainBodyChunk.pos.x == self.player.input[0].x > 0)
                {
                    num19 = -1;
                }
                if (num19 > -1)
                {
                    self.hands[num19].reachingForObject = true;
                    self.hands[num19].absoluteHuntPos   = self.objectLooker.mostInterestingLookPoint;
                    if (num == 0f)
                    {
                        self.drawPositions[0, 0] += Custom.DirVec(self.drawPositions[0, 0], self.objectLooker.mostInterestingLookPoint) * 5f;
                        self.head.vel            += Custom.DirVec(self.drawPositions[0, 0], self.objectLooker.mostInterestingLookPoint) * 2f;
                    }
                }
            }
        }
        for (int num20 = 0; num20 < 2; num20++)
        {
            self.hands[num20].Update();
        }
        if (self.player.sleepCurlUp > 0f)
        {
            float   num21   = Mathf.Sign(self.player.bodyChunks[0].pos.x - self.player.bodyChunks[1].pos.x);
            Vector2 vector3 = (self.player.bodyChunks[0].pos + self.player.bodyChunks[1].pos) / 2f;
            self.drawPositions[0, 0]    = Vector2.Lerp(self.drawPositions[0, 0], vector3, self.player.sleepCurlUp * 0.2f);
            self.drawPositions[1, 0]    = Vector2.Lerp(self.drawPositions[1, 0], vector3, self.player.sleepCurlUp * 0.2f);
            self.drawPositions[0, 0].y += 2f * self.player.sleepCurlUp;
            self.drawPositions[1, 0].y += 2f * self.player.sleepCurlUp;
            self.drawPositions[1, 0].x -= 3f * num21 * self.player.sleepCurlUp;
            for (int num22 = 0; num22 < self.tail.Length; num22++)
            {
                float num23 = (float)num22 / (float)(self.tail.Length - 1);
                self.tail[num22].vel *= 1f - 0.2f * self.player.sleepCurlUp;
                self.tail[num22].pos  = Vector2.Lerp(self.tail[num22].pos, self.drawPositions[1, 0] + new Vector2((Mathf.Sin(num23 * 3.1415927f) * 25f - num23 * 10f) * -num21, Mathf.Lerp(5f, -15f, num23)), 0.1f * self.player.sleepCurlUp);
            }
            self.head.vel *= 1f - 0.4f * self.player.sleepCurlUp;
            self.head.pos  = Vector2.Lerp(self.head.pos, vector3 + new Vector2(num21 * 5f, -3f), 0.5f * self.player.sleepCurlUp);
            if (self.player.sleepCurlUp == 1f || Random.value < 0.033333335f)
            {
                self.blink = Math.Max(2, self.blink);
            }
            for (int num24 = 0; num24 < 2; num24++)
            {
                self.hands[num24].absoluteHuntPos = vector3 + new Vector2(num21 * 10f, -20f);
            }
        }
        if (self.player.Adrenaline > 0f)
        {
            float d2 = Mathf.Pow(self.player.Adrenaline, 0.2f);
            self.drawPositions[0, 0] += Custom.RNV() * Random.value * d2 * 2f;
            self.drawPositions[0, 1] += Custom.RNV() * Random.value * d2 * 2f;
            self.head.pos            += Custom.RNV() * Random.value * d2 * 1f;
            if (Random.value < 0.05f)
            {
                self.blink = Math.Max(self.blink, 3);
            }
        }
    }
Example #23
0
        /// <summary>
        /// If segment rotation is in too big angle we straighten it
        /// </summary>
        protected Vector3 AngleLimiting(TailSegment child, Vector3 targetPos)
        {
            float angleFactor = 0f;

            _limiting_limitPosition = targetPos;


            _limiting_angle_ToTargetRot = (
                Quaternion.FromToRotation
                (
                    child.ParentBone.transform.TransformDirection(child.LastKeyframeLocalPosition),
                    targetPos - child.ParentBone.ProceduralPosition)
                )
                                          * child.ParentBone.transform.rotation;

            _limiting_angle_targetInLocal = FEngineering.QToLocal(child.ParentBone.transform.rotation, _limiting_angle_ToTargetRot); // Quaternion.Inverse(child.ParentBone.PreviousRotation) * _limiting_angle_ToTargetRot;


            // Limiting all axis or one
            float angleDiffToInitPose = 0f;

            if (AngleLimitAxis.sqrMagnitude == 0f) // All axis limit angle
            {
                angleDiffToInitPose = Quaternion.Angle(_limiting_angle_targetInLocal, child.LastKeyframeLocalRotation);
            }
            else // Selective axis
            {
                #region Selective axis limits

                AngleLimitAxis.Normalize();

                if (LimitAxisRange.x == LimitAxisRange.y)
                {
                    angleDiffToInitPose = Mathf.DeltaAngle(
                        Vector3.Scale(child.InitialLocalRotation.eulerAngles, AngleLimitAxis).magnitude,
                        Vector3.Scale(_limiting_angle_targetInLocal.eulerAngles, AngleLimitAxis).magnitude);

                    if (angleDiffToInitPose < 0f)
                    {
                        angleDiffToInitPose = -angleDiffToInitPose;
                    }
                }
                else
                {
                    angleDiffToInitPose = Mathf.DeltaAngle(
                        Vector3.Scale(child.InitialLocalRotation.eulerAngles, AngleLimitAxis).magnitude,
                        Vector3.Scale(_limiting_angle_targetInLocal.eulerAngles, AngleLimitAxis).magnitude);

                    if (angleDiffToInitPose > LimitAxisRange.x && angleDiffToInitPose < LimitAxisRange.y)
                    {
                        angleDiffToInitPose = 0f;
                    }
                    if (angleDiffToInitPose < 0)
                    {
                        angleDiffToInitPose = -angleDiffToInitPose;
                    }
                }

                #endregion
            }


            #region Debug
            //Debug.Log("Atarget in local = " +
            //    FEngineering.WrapVector(_limiting_angle_targetInLocal.eulerAngles) + " last key local = " +
            //    FEngineering.WrapVector(child.lastKeyframeLocalRotation.eulerAngles) + " angle = " + angleDiffToInitPose);
            #endregion

            // Finding rotate back to limited angle coordinates
            if (angleDiffToInitPose > AngleLimit)
            {
                float exceededAngle = Mathf.Abs(Mathf.DeltaAngle(angleDiffToInitPose, AngleLimit));
                angleFactor = Mathf.InverseLerp(0f, AngleLimit, exceededAngle); // percentage value (0-1) from target rotation to limit

                #region Debug

                //Debug.DrawLine(child.ParentBone.ParentBone.transform.position + child.ParentBone.ParentBone.ProceduralRotation * child.ParentBone.transform.localPosition,
                //child.ProceduralPosition, Color.red, 1f);

                //Debug.Log("[" + child.Index + "] diff = "
                //    + angleDiffToInitPose + " exc =  "
                //    + exceededAngle + " fact = "
                //    + angleFactor);

                #endregion


                if (LimitSmoothing > Mathf.Epsilon)
                {
                    float smooth = Mathf.Lerp(55f, 15f, LimitSmoothing);
                    _limiting_angle_newLocal = Quaternion.SlerpUnclamped(_limiting_angle_targetInLocal, child.LastKeyframeLocalRotation, deltaForLerps * smooth * angleFactor);
                }
                else
                {
                    _limiting_angle_newLocal = Quaternion.SlerpUnclamped(_limiting_angle_targetInLocal, child.LastKeyframeLocalRotation, angleFactor);
                }


                _limiting_angle_ToTargetRot = FEngineering.QToWorld(child.ParentBone.transform.rotation, _limiting_angle_newLocal);
                _limiting_limitPosition     = child.ParentBone.ProceduralPosition + _limiting_angle_ToTargetRot * Vector3.Scale(child.transform.lossyScale, child.LastKeyframeLocalPosition);
            }

            if (angleFactor > Mathf.Epsilon)
            {
                return(_limiting_limitPosition);
            }
            else
            {
                return(targetPos);
            }
        }
        void SimulateTailMotionFrame(bool pp)
        {
            #region Prepare base positions calculation for tail segments to use in coords calculations and as reference

            TailSegments_UpdateRootFeatures();

            TailSegments_UpdateCoordsForRootBone(_tc_rootBone);

            if (pp)
            {
                PostProcessing_ReferenceUpdate();
            }


            if (_tc_startI > -1)
            {
                TailSegment child = TailSegments[_tc_startI]; // Used in while() loops below
                                                              // Going in while is 2x faster than for(i;i;i) loop
                while (child != GhostChild)
                {
                    // Preparing parameter values adapted to stiff and slithery character and blended
                    TailSegment_PrepareMotionParameters(child);

                    // Velocity changes detection
                    TailSegment_PrepareVelocity(child);

                    child = child.ChildBone;
                }
            }

            // Udpate for artificial end bone
            TailSegment_PrepareMotionParameters(GhostChild);
            TailSegment_PrepareVelocity(GhostChild);

            #endregion

            #region Processing segments, calculating full target coords and apply to transforms

            if (_tc_startII > -1)
            {
                // Ignoring root related calculations
                TailSegment child = TailSegments[_tc_startII];

                while (child != GhostChild)
                {
                    TailSegment_BaseSwingProcessing(child);

                    // Pre processing with limiting, gravity etc.
                    TailCalculations_SegmentPreProcessingStack(child);

                    if (pp)
                    {
                        TailCalculations_SegmentPostProcessing(child);
                    }

                    // Blending animation weight
                    TailSegment_PreRotationPositionBlend(child);

                    child = child.ChildBone;
                }
            }

            // Applying processing for artificial child bone without transform
            TailCalculations_UpdateArtificialChildBone(GhostChild);

            #endregion
        }