Skip to content

Add override argument to setAnalogControlState #1852

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 11, 2020

Conversation

LosFaul
Copy link
Contributor

@LosFaul LosFaul commented Nov 20, 2020

This PR adds a frameForced argument to setAnalogControlState
this allows me to solve my issues i had here: #567
Fixes #567

setAnalogControlState(string state[, float state ][, bool forceOverrideNextFrame = false])

old behavior (override = false)
- player input will not be overwitten if it's unequals to 0
- otherwise it will use the last set value after player input went 0 every following frame

behavior with (override = true)
- will overwrite the player input even if it's not 0, but only for the next frame

example edge case:
todo the way setAnalogControlState works
you can in case of a script were you want to invert player controlls only get the player value
with getAnalogControlState if you use set the raw value to true
this is because the opposite control value is always set to 0 except for accelerate and brake

some code examples:

Allows to perfectly switch left right steering of the player
can be usefull for fun race maps with item pickup scripts :)

addEventHandler("onClientPreRender", root,
    function()
        local right = getAnalogControlState("vehicle_right", true)
        local left = getAnalogControlState("vehicle_left", true)
        
        if right > left then
            setAnalogControlState("vehicle_left", right, true)
        else
            setAnalogControlState("vehicle_right", left, true)
        end
    end
)

Allows to make traction control for custom handlings with very aggressive acceleration
for example: take bullet and use this code with runcode
srun setVehicleHandling(me.vehicle, "engineAcceleration", 50) setVehicleHandling(me.vehicle, "maxVelocity", 400)
then try to drive with and with out traction controll script

addEventHandler("onClientPreRender", root,
    function()
        local vehicle = getPedOccupiedVehicle(localPlayer)
        if vehicle then

            local rearLeft = getVehicleWheelFrictionState(vehicle, 1)
            local rearRight = getVehicleWheelFrictionState(vehicle, 3)
            local rl = tostring(isVehicleWheelOnGround(vehicle, 1))
            local rr = tostring(isVehicleWheelOnGround(vehicle, 3))

            local input = getAnalogControlState("accelerate")
            local tC = 1
            if rl and rr and rearLeft == 1 and rearRight == 1 then
                tC = 0.3
            end
            setAnalogControlState("accelerate", input * tC, true)
        end
    end
)

there is also a lot more use stuff where this can be usefull
but the most important is:

  • first it doesn't require weird script hacks anymore for keyboard
  • second it works for gamepad players too

@qaisjp
Copy link
Contributor

qaisjp commented Nov 20, 2020

What happens if you call getAnalogControlState after a call to this?

@LosFaul
Copy link
Contributor Author

LosFaul commented Nov 20, 2020

for example:
if player input 0.9
setAnalogControlState("accelerate", 0.5, true)
getAnalogControlState("accelerate") -- returns scripted value 0.5
getAnalogControlState("accelerate", true) -- returns player input 0.9

in the next frame and player input still 0.9
if not setAnalogControlState("accelerate", ...) called
getAnalogControlState("accelerate") -- returns scripted value 0.9
getAnalogControlState("accelerate", true) -- returns player input 0.9

@qaisjp
Copy link
Contributor

qaisjp commented Nov 20, 2020

But what if there is no controller plugged in? Getter returns 0 when no controller is plugged in and the W key is pressed, and rawValue=true

@LosFaul
Copy link
Contributor Author

LosFaul commented Nov 20, 2020

the same except that player input would be 1

@Pirulax Pirulax added enhancement New feature or request and removed enhancement New feature or request labels Nov 20, 2020
@Pirulax
Copy link
Contributor

Pirulax commented Nov 20, 2020

So this is a bugfix / enchantment?

@LosFaul
Copy link
Contributor Author

LosFaul commented Nov 20, 2020

well i kind of both
i didn't wanted to make a "fix"
since some old scripts might depend on the old behavior

basicly ensuring backwards compatibility

@Pirulax Pirulax added bug Something isn't working enhancement New feature or request labels Nov 20, 2020
@qaisjp
Copy link
Contributor

qaisjp commented Nov 20, 2020

the same except that player input would be 1

But getAnalogControlState says:

rawValue: A bool indicating whether to poll for raw controller state, which ignores keyboard input and any overrides from setAnalogControlState and others. When set to true, and a controller is not used, the function will always return 0.

@LosFaul
Copy link
Contributor Author

LosFaul commented Nov 21, 2020

the same except that player input would be 1

But getAnalogControlState says:

rawValue: A bool indicating whether to poll for raw controller state, which ignores keyboard input and any overrides from setAnalogControlState and others. When set to true, and a controller is not used, the function will always return 0.

thanks for your reply, i didn't check getAnalogControlState properly
will come back here as soon i did check it properly

@LosFaul
Copy link
Contributor Author

LosFaul commented Nov 21, 2020

the same except that player input would be 1

But getAnalogControlState says:

rawValue: A bool indicating whether to poll for raw controller state, which ignores keyboard input and any overrides from setAnalogControlState and others. When set to true, and a controller is not used, the function will always return 0.

i checked release and this is doesn't seem to be case for every control
so the wiki information seems wrong

@LosFaul
Copy link
Contributor Author

LosFaul commented Nov 21, 2020

the same except that player input would be 1

But getAnalogControlState says:

rawValue: A bool indicating whether to poll for raw controller state, which ignores keyboard input and any overrides from setAnalogControlState and others. When set to true, and a controller is not used, the function will always return 0.

i checked release and this is doesn't seem to be case for every control
so the wiki information seems wrong

we both have missunderstood the meaning of controller in this case
controller refers to the player it self and the controller input has nothing todo with it if you use keyboard or gamepad
since it only represents the player input value

@LosFaul
Copy link
Contributor Author

LosFaul commented Nov 21, 2020

after clearing up a lot confusion i had a few times my self

i checked and tested everything carefully again:
getAnalogControlState and rawValue=false
-> you will always get the control state value as before my changes
getAnalogControlState and rawValue=true
-> you will always get the player input as before my changes

@LosFaul
Copy link
Contributor Author

LosFaul commented Nov 24, 2020

btw. if someone asks why the value is only forced for one frame:
the problem is that the value would be otherwise forced until the forced argument is set to false again
which might be not the best way to handle it and this would remain until a reconnect
also in most cases you would want to be able to dynamicly change the input anyway

@LosFaul
Copy link
Contributor Author

LosFaul commented Nov 25, 2020

renamed frameForced to override

@LosFaul LosFaul changed the title add frameForced argument to setAnalogControlState add override argument to setAnalogControlState Nov 25, 2020
@LosFaul
Copy link
Contributor Author

LosFaul commented Nov 28, 2020

has someone suggestions what could be changed?

static void RemoveSetAnalogControlState(const char* szName);

static void ProcessSetAnalogControlState(CControllerState& cs, bool bOnFoot);
static void ProcessControl(short& usControlValue, unsigned int uiIndex, bool bResetCmp);
static void ProcessControl(short& usControlValue, unsigned int uiIndex); //, bool bPositive
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure what this comment is supposed to mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overlooked it while cleaning up :x
i also made some small refactors while working on the stuff and removed some redundant code

@Pirulax
Copy link
Contributor

Pirulax commented Nov 29, 2020

The code looks good.
I haven't tested it, but I hope you did :D
Just make sure it works as expected.

@Pirulax
Copy link
Contributor

Pirulax commented Nov 29, 2020

renamed frameForced to override

I think frameForced is a more accurate name tho.
Also, regarding the controller is actually the player thing, could you clarify this on the wiki page as well?

@LosFaul
Copy link
Contributor Author

LosFaul commented Nov 29, 2020

renamed frameForced to override

I think frameForced is a more accurate name tho.
Also, regarding the controller is actually the player thing, could you clarify this on the wiki page as well?

  1. i asked botder if he could give me a quick review, so i cleaned up some things
    but if you think frameForced is better naming than override i can rename it back
    -> alternatively we could also name it overrideFrame or something
  2. already updated wiki pages ;)

@Pirulax
Copy link
Contributor

Pirulax commented Nov 29, 2020

As of my understanding 'override' (aka 'frameForced') means that its forced for a frame, right?

@LosFaul
Copy link
Contributor Author

LosFaul commented Nov 29, 2020

As of my understanding 'override' (aka 'frameForced') means that its forced for a frame, right?

yes, which i personally believe is more practical

first of all i believe the main usage would be frame based anyway
specially if you want to modify the player input dynamicly

second if you have for example a race map with a script
it would not clean the force state up automaticly when the map ends
and you would be at the mercy of the map maker to disable the forced input on the resource stop event or need to add extra code in the gamemode resource

but if it's only forced for a frame
you don't need to worry about it and don't need any extra code to clean the forced state up

@4O4
Copy link
Contributor

4O4 commented Nov 29, 2020

I think the name should clearly state that it's effective for one frame only, and the verb part can be "override", "force" or whatever as long as this lifetime part is included in the name. So my suggestions would be something like overrideForOneFrame, forceForOneFrame (or go full verbose with overrideControllerStateForOneFrame 😄). What do you guys think?

@LosFaul
Copy link
Contributor Author

LosFaul commented Nov 29, 2020

i would keep out "controller" from the name, since many people will automaticly associate it with gamepads
which is in this case wrong

since it affects the next called game position update, i would suggest:
overrideNextFrame or forceNextFrame

@4O4
Copy link
Contributor

4O4 commented Nov 29, 2020

i would keep out "controller" from the name, since many people will automaticly associate it with gamepads
which is in this case wrong

Agreed. Controller was just for an example of maybe-overly-verbose name here, but it is definitely a bad choice. "Input device" or maybe also "hardware" (although one can argue that it is not always hardware as they can be emulated) are probably the only generic enough names to cover it precisely.

But anyway your latest suggestions sound reasonable too 😉

@LosFaul
Copy link
Contributor Author

LosFaul commented Nov 30, 2020

called it now: forceOverrideNextFrame

@botder botder merged commit fc17353 into multitheftauto:master Dec 11, 2020
@StrixG StrixG added this to the 1.6 milestone Dec 11, 2020
@ghost ghost mentioned this pull request Dec 11, 2020
@patrikjuvonen patrikjuvonen changed the title add override argument to setAnalogControlState Add override argument to setAnalogControlState Aug 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix setAnalogControlState
6 participants