1 (edited by BlankMauser 2021-05-13 16:00:51)

Topic: [Temporary Fix] Diagonal Inputs And Button Charge Moves

Currently there are plans to fix the Input System and refactor it into something much more efficient. This is because UFE's Input system has been iterated over the years with new functions beyond its original intention. Some functionality is missing and in this thread I will detail some as well as work-arounds for the issues. For convenience I will pastebin my Input Managers at the end.

Issue 1: Diagonal Holding

Diagonal inputs are injected separately from cardinals and don't have a lot of the same functionality. They don't behave the same when used as button executions or charge moves. Doing moves that end on up-forward or down-forward work fine for instance, but these two input options will not yield the same results:

https://i.gyazo.com/3c0d0f103c9204586ad106b89e90a04c.pnghttps://i.gyazo.com/2abeb16f7cd71fece14c6495f8ff5152.png

You would expect to be able to hold down back and press button 2 to get the result you want in the first picture, however doing this doesn't result in a successful input. The 2nd picture behaves exactly like that. You can hold back and press Button 2, resulting in a successful input.

In order to circumvent this, we will be using Rewired but the same concept can be applied to any input system. If you haven't already installed Rewired follow this guide.

You will also want to go into UFE.CS and make this change at line 2200:

                case InputManagerType.Rewired:
                    playerController.humanController = goPlayerManager.AddComponent<RewiredInputController>();
                    (playerController.humanController as RewiredInputController).rewiredPlayerId = i;

this is to fix an issue causing player id to always be 0.

We will be adding the following lines in RewiredInputController.cs under "ReadInput"

                if (buttonName == "Button7")
                {
                    return new InputEvents(
                        (inputSource.GetNegativeButton(rewiredPlayerId, "Horizontal") && inputSource.GetNegativeButton(rewiredPlayerId, "Vertical"))
                    );
                }

                if (buttonName == "Button8")
                {
                    return new InputEvents(
                        (inputSource.GetButton(rewiredPlayerId, "Horizontal") && inputSource.GetNegativeButton(rewiredPlayerId, "Vertical"))
                    );
                }

and adding NegativeButton checks in RewiredUFEInputManager.cs like so:

        public bool GetNegativeButton(int playerId, string name)
        {
            if (!_initialized || !isEnabled) return false;
            return ReInput.players.GetPlayer(playerId).GetNegativeButton(name);
        }

This changes Button7 and Button8 to be custom buttons that are only pressed when the "Diagonal" conditions are true. These fake "buttons" must also be setup in your UFE global config under "Input Options" like so:

https://i.gyazo.com/b7a48e695d20e036ae7934c0268c0a31.png

And your new Input would be something like this:

https://i.gyazo.com/db1c2330e08995f7ca80ccb7e1e29619.png

voila! Your inputs should now work as intended!

https://media2.giphy.com/media/91Y3TtGlW7o1FrpSOs/giphy.gif?cid=790b76115f16b5492e0d5234d987002f55c757f3c25dd8a9&amp;rid=giphy.gif&amp;ct=g

Of course, some more changes need to be done to achieve the right functionality. In ControlsScript under //Button Press you'll want to make these changes:

                    if (ev.button)
                    {

                        //Mirror DownBack and DownRight proxies
                        if (inputRef.inputButtonName == "Button7")
                        {
                            if (mirror == 1)
                            {
                                inputHeldDown[ButtonPress.Button7] = 0;
                                inputRef.engineRelatedButton = ButtonPress.Button8;
                            }
                            else
                            {
                                inputHeldDown[ButtonPress.Button8] = 0;
                                inputRef.engineRelatedButton = ButtonPress.Button7;
                            }
                        }
                        
                        if (inputRef.inputButtonName == "Button8")
                        {
                            if (mirror == 1)
                            {
                                inputHeldDown[ButtonPress.Button8] = 0;
                                inputRef.engineRelatedButton = ButtonPress.Button7;
                            }
                            else
                            {
                                inputHeldDown[ButtonPress.Button7] = 0;
                                inputRef.engineRelatedButton = ButtonPress.Button8;
                            }
                        }

Same with under //Plinking

                                if (inputRef2 != inputRef && (inputRef2.inputType == InputType.Button && button2Down || inputHeldDown[inputRef2.engineRelatedButton] > 0))
                                {
                                    //Mirror DownBack and DownRight proxies
                                    if (inputRef2.inputButtonName == "Button7")
                                    {
                                        if (mirror == 1)
                                        {
                                            inputHeldDown[ButtonPress.Button7] = 0;
                                            inputRef2.engineRelatedButton = ButtonPress.Button8;
                                        }
                                        else
                                        {
                                            inputHeldDown[ButtonPress.Button8] = 0;
                                            inputRef2.engineRelatedButton = ButtonPress.Button7;
                                        }
                                    }
                                    
                                    if (inputRef2.inputButtonName == "Button8")
                                    {
                                        if (mirror == 1)
                                        {
                                            inputHeldDown[ButtonPress.Button8] = 0;
                                            inputRef2.engineRelatedButton = ButtonPress.Button7;
                                        }
                                        else
                                        {
                                            inputHeldDown[ButtonPress.Button7] = 0;
                                            inputRef2.engineRelatedButton = ButtonPress.Button8;
                                        }
                                    }

This makes sure the buttons will mirror correctly on both sides. Next, you'll want to make sure that you skip the plink check, otherwise players will get the input on 2~DownBack and other undesirable results

  inputHeldDown[inputRef.engineRelatedButton] += UFE.fixedDeltaTime;

                        if (inputRef.engineRelatedButton == ButtonPress.Button7 || inputRef.engineRelatedButton == ButtonPress.Button8)
                        {
                            goto PlinkSkip;
                        }

                        // Plinking
                        if (buttonDown && inputHeldDown[inputRef.engineRelatedButton] <= ((Fix64)UFE.config.plinkingDelay / UFE.config.fps))
                        {
                            foreach (InputReferences inputRef2 in currentInputs.Keys)
                            {

                                InputEvents ev2 = currentInputs[inputRef2];
                                InputEvents p2;
                                if (!previousInputs.TryGetValue(inputRef2, out p2))
                                {
                                    p2 = InputEvents.Default;
                                }
                                bool button2Down = ev2.button && !p2.button;

                                if (inputRef2 != inputRef && (inputRef2.inputType == InputType.Button && button2Down || inputHeldDown[inputRef2.engineRelatedButton] > 0))
                                {
                                    //Mirror DownBack and DownRight proxies
                                    if (inputRef2.inputButtonName == "Button7")
                                    {
                                        if (mirror == 1)
                                        {
                                            inputHeldDown[ButtonPress.Button7] = 0;
                                            inputRef2.engineRelatedButton = ButtonPress.Button8;
                                        }
                                        else
                                        {
                                            inputHeldDown[ButtonPress.Button8] = 0;
                                            inputRef2.engineRelatedButton = ButtonPress.Button7;
                                        }
                                    }
                                    
                                    if (inputRef2.inputButtonName == "Button8")
                                    {
                                        if (mirror == 1)
                                        {
                                            inputHeldDown[ButtonPress.Button8] = 0;
                                            inputRef2.engineRelatedButton = ButtonPress.Button7;
                                        }
                                        else
                                        {
                                            inputHeldDown[ButtonPress.Button7] = 0;
                                            inputRef2.engineRelatedButton = ButtonPress.Button8;
                                        }
                                    }

                                    inputHeldDown[inputRef2.engineRelatedButton] += UFE.fixedDeltaTime;


                                    MoveInfo tempMove = myMoveSetScript.GetMove(
                                        new ButtonPress[] { inputRef.engineRelatedButton, inputRef2.engineRelatedButton }, 0, currentMove, false, (inputRef.inputType == InputType.Button && inputRef2.inputType == InputType.Button));

                                    if (tempMove != null)
                                    {
                                        if (myMoveSetScript.CanPlink(currentMove, tempMove))
                                            KillCurrentMove();

                                        storedMove = tempMove;
                                        storedMoveTime = (Fix64)UFE.config.executionBufferTime / UFE.config.fps;
                                    }
                                }
                            }
                        }
                    }


                    if (buttonDown)
                    {
                        MoveInfo tempMove = myMoveSetScript.GetMove(new ButtonPress[] { inputRef.engineRelatedButton }, 0, currentMove, false);
                        if (tempMove != null)
                        {
                            // If plinking occured and input sequence is higher then the plinked move, override it
                            if (storedMove == null || tempMove.defaultInputs.buttonSequence.Length > storedMove.defaultInputs.buttonSequence.Length)
                            {
                                storedMove = tempMove;
                                storedMoveTime = (UFE.config.executionBufferTime / (Fix64)UFE.config.fps);
                            }
                            return;
                        }

                        // Test regular jump if input type is button
                        if (!myInfo.customControls.disableJump && inputRef.engineRelatedButton == myInfo.customControls.jumpButton)
                        {
                            ExecuteJump(inputRef.engineRelatedButton, false);
                        }
                        // Test crouch if input type is button
                        else if (!myInfo.customControls.disableCrouch && inputRef.engineRelatedButton == myInfo.customControls.crouchButton)
                        {
                            ExecuteCrouch();
                        }
                    }

                    PlinkSkip:

Issue 2: Button Release Charge Moves

Button Releases tend to have some bugs as they rely on "storedMove" checks. They also can not activate on a charge move like so:

https://i.gyazo.com/1453f3e236b5e9c250e13a1f726812cb.png

This is a common input for things like Balrog's TAP punch. We can do a similar fix by creating fake "buttons" that rely on Rewireds button release check:

                if (buttonName == "Button9")
                {
                    return new InputEvents(
                        inputSource.GetButtonUp(rewiredPlayerId, "Button1")
                    );
                }

                if (buttonName == "Button10")
                {
                    return new InputEvents(
                        inputSource.GetButtonUp(rewiredPlayerId, "Button2")
                    );
                }

With our new setup we can now do charge moves using buttons that activate upon negative edge:

https://media3.giphy.com/media/UALObGEZjaULWpQHeK/giphy.gif?cid=790b761177190d110b3de8a513154f82ea2da586ba2abbad&amp;rid=giphy.gif&amp;ct=g

Make sure to set up these "buttons" in the input config as well.

Here are the pastebins for my Input Managers:

https://pastebin.com/S4kAqryN - RewiredUFEInputManager.cs
https://pastebin.com/bcFR5TQM - RewiredInputController.cs

Again, this is all a temporary workaround. The plan is to refactor the input system for UFE3. You can also set up custom button icons for these inputs so they display correctly in the input viewer.

Cheers

Share

Thumbs up +2 Thumbs down