public override void PlayerControl(Input input)
        {
            Vector2 newstickpos = input.GetRightStick(shovelReach, true);//input.GetRightStick();
            Vector2 pos = newstickpos * shovelReach;
            Vector2 worldStickPos = parent.body.pos + pos;
            Vector2 diff = worldStickPos - shovelNode.body.pos;
            //float angle = Utils.VectorToAngle(shovelNode.body.pos - parent.body.pos) + VMath.PIbyTwo % VMath.twoPI;
            Vector2 shovelDir = shovelNode.body.pos - parent.body.pos;
            shovelDir = new Vector2(shovelDir.Y, -shovelDir.X);
            shovelNode.body.SetOrientV2(shovelDir);

            if (modeShovelPosition == ModeShovelPosition.AbsoluteStickPos)
            {
                shovelNode.body.pos = worldStickPos;
            }
            else if (modeShovelPosition == ModeShovelPosition.PhysicsBased)
            {
                float len = diff.Length();
                if (len < 1)
                {
                    shovelNode.body.velocity = Vector2.Zero;
                }
                else
                {
                    float velLen = shovelNode.body.velocity.Length();

                    Vector2 diffcopy = diff;
                    VMath.NormalizeSafe(ref diffcopy);

                    Vector2 normalizedVel = shovelNode.body.velocity;
                    VMath.NormalizeSafe(ref normalizedVel);

                    float result = 0;
                    Vector2.Dot(ref diffcopy, ref normalizedVel, out result);

                    diffcopy *= result;
                    Vector2 force = (diff / physicsDivisor);
                    if (shovelling && compoundedMass >= 1) force /= compoundedMass * 1;
                    shovelNode.body.velocity = diffcopy + force;
                    //shovelNode.body.ApplyForce(force);
                }
            }

            if (shovelling)
            {
                //if (fc.newGamePadState.Triggers.Right < deadzone && fc.oldGamePadState.Triggers.Right > deadzone)
                if (input.BtnReleased(InputButtons.RightTrigger_Mouse1))
                {
                    shovelling = false;
                    foreach(Node n in shovelLink.targets.ToList())
                    {
                        if (physicsThrow)
                        {
                            n.body.velocity = n.body.effvelocity;
                        }
                        else
                        {
                            Vector2 stickdirection = newstickpos;
                            VMath.NormalizeSafe(ref stickdirection);

                            n.body.velocity = stickdirection * throwSpeed;
                        }
                        n.collision.active = true;
                        shovelLink.targets.Remove(n);
                        n.body.ClearExclusionChecks();
                        n.body.color = n.body.permaColor;
                    }
                    shovelLink.formation.UpdateFormation();
                    shovelLink.active = false;
                    shovelNode.room.AllActiveLinks.Remove(shovelLink);
                    compoundedMass = 0f;
                }
            }
            else
            {
                if (input.BtnClicked(InputButtons.RightTrigger_Mouse1))
                {
                    shovelling = true;
                    ObservableHashSet<Node> capturedNodes = new ObservableHashSet<Node>();
                    int count = 0;
                    Action<Collider, Collider> del = delegate(Collider c1, Collider c2){
                        if (count >= maxShovelCapacity) return;
                        if (c2.parent.dataStore.ContainsKey("shovelnodeparent"))return;
                        if (c2.parent.HasComp<Diode>()) return;
                        if (modePlayers != ModePlayers.GrabBoth && c2.parent.IsPlayer)
                        {
                            if (modePlayers == ModePlayers.GrabNone) return;
                            if (modePlayers == ModePlayers.GrabSelf && c2.parent != parent) return;
                            if (modePlayers == ModePlayers.GrabOtherPlayers && c2.parent == parent) return;
                        }
                        float dist = Vector2.Distance(c1.pos, c2.pos);
                        if (dist <= scoopReach)
                        {
                            count++;
                            capturedNodes.Add(c2.parent);
                            c2.parent.body.color = parent.body.color;
                        }
                    };
                    shovelNode.room.gridsystemAffect.retrieveOffsetArraysAffect(shovelNode.body, del, scoopReach * 2);
                    shovelLink.targets = capturedNodes;
                    shovelLink.formation.UpdateFormation();
                    shovelLink.active = true;
                    shovelNode.room.AllActiveLinks.Add(shovelLink);
                    compoundedMass = 0f;
                    foreach(Node n in capturedNodes)
                    {
                        n.collision.active = false;
                        compoundedMass += n.body.mass;
                    }
                }
            }
        }
        public override void PlayerControl(Input input)
        {
            if (state == GunState.inactive)
            {
                if (input.BtnClicked(InputButtons.RightTrigger_Mouse1))
                {
                    state = GunState.extending;
                    Vector2 dir = input.GetRightStick().NormalizeSafe() * shootNodeSpeed + parent.body.velocity;
                    shootNode.body.pos = parent.body.pos + dir * 5;
                    shootNode.body.velocity = dir;
                    shootNode.active = true;

                    grav.active = false;
                    spring.active = true;
                    shootLink.active = true;

                }
            }
            else if (state == GunState.extending)
            {
                if (input.BtnReleased(InputButtons.RightTrigger_Mouse1))
                {
                    state = GunState.retracting;
                    grav.active = true;
                    spring.active = false;
                }
            }
            else if (state == GunState.retracting)
            {
                shootNode.body.velocity = VMath.Redirect(shootNode.body.velocity, parent.body.pos - shootNode.body.pos);
                float catchZone = 20f; //1f for bipedal action
                if ((parent.body.pos - shootNode.body.pos).Length() < catchZone)
                {
                    state = GunState.inactive;
                    shootNode.active = false;
                    shootLink.active = false;
                }
            }

            if (input.BtnClicked(InputButtons.RightBumper_E))
            {
                if (attachedNodesQueue.Count > 0)
                {
                    Node n = attachedNodesQueue.Dequeue();
                    if (attachLink.targets.Contains(n))
                    {
                        attachLink.targets.Remove(n);
                    }
                    if (attachLink.sources.Contains(n))
                    {
                        attachLink.sources.Remove(n);
                    }
                    if (attachLink.formation.chainList.Contains(n))
                    {
                        attachLink.formation.chainList.Remove(n);
                    }
                    if (attachedNodesQueue.Count == 0)
                    {
                        attachLink.active = false;
                    }
                    attachLink.formation.UpdateFormation();
                }
            }

            if (input.BtnClicked(InputButtons.LeftBumper_Q))
            {
                if (attachedNodesQueue.Count > 0)
                {
                    if (attachedNodesQueue.Count != 0)
                        attachedNodesQueue = new Queue<Node>();
                    if (attachLink.targets.Count != 0)
                        attachLink.targets = new ObservableHashSet<Node>();

                    if (!attachLink.sources.Contains(parent))
                    {
                        attachLink.formation.ClearChain();
                        if (attachLink.sources.Count != 0)
                            attachLink.sources = new ObservableHashSet<Node>();
                    }

                    attachLink.active = false;
                }
            }

            if (attachLink.active)
            {
                float amountPushed = 1f - input.newInputState.LeftTriggerAnalog;
                amountPushed = amountPushed * 100 + 50;
                if (attachLink.HasComp<Tether>())
                {
                    attachLink.Comp<Tether>().maxdist = (int)amountPushed;
                    attachLink.Comp<Tether>().mindist = (int)amountPushed;
                }
                if (attachLink.HasComp<Spring>())
                {
                    attachLink.Comp<Spring>().restdist = (int)amountPushed;
                }
            }
        }