Author Topic: Run a python script using voiceattack (requires user to enter two inputs)  (Read 7258 times)

stoopidsxyflanders

  • Guest
Hey guys,

I want to be able to run this program in voiceattack so I don't need to alt-tab out of the game and have to remember co-ordinates each time I alt-tab: https://trinket.io/python/6030d41847

So basically I want it to work like this..

  • I say a phrase to start a multi-part command e.g. "Start Mortar Calculations"
  • VA responds asking for co-ordinates of mortar e.g. "What grid is the mortar in?"
  • I respond with co-ordinates of mortar e.g. "Alpha Nine Keypad 3 Subgrid 9"
  • VA confirms what I said e.g. "Alpha Nine Keypad 3 Subgrid 9. Confirm?"
  • I respond with confirm or reject e.g. "Confirm"
  • VA saves result as string e.g. $mortargrid
  • VA asks for co-ordinates of target e.g. "What grid is your target?"
  • I respond with co-ordinates of target e.g. "Charlie Nine Keypad 3 Subgrid 9"
  • VA confirms what I said e.g. "Charlie Nine Keypad 3 Subgrid 9. Confirm?"
  • I respond with confirm or reject e.g. "Confirm"
  • VA saves results as a string e.g. $targetgrid
  • VA loads the python script in the background and enters in $mortargrid and $targetgrid and runs the script
  • VA reads out the result e.g. "Set bearing to 184 degrees. Set elevation to 1,245 mil"
  • I can ask it to repeat the result if needed e.g. "Repeat last"

I know it's complicated so first I want to know if it can be done. If so, just give me a few things to google and hopefully I'll be able to figure it out myself. I don't expect anyone to actually write the whole thing for me, I know that's asking way too much.

Exergist

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 405
  • Ride the lightning
Well I can certainly offer the methodology I use for obtaining user input, specifically Yes/No confirmation. I've attached some of the commands and show the code for ease of viewing below from my Mass Effect 3 profile (WIP).

The example shows my command for Reset Game Data (clearing saved profile variables). It hinges on getting information from the user via a Query command and a Response command. The query voices a predefined question, provides this same question via text in the event log, provides a "hint" that shows the type of voice input expected of the user, and counts down 5 seconds while waiting for a user response. The user response is a separate command that is fully enabled by a flag (input request) in the query command. Once a "response" has been detected that is valid (and there's some looping built in to give the user multiple chances to provide an expected response) then additional processing occurs based on the response. Bear in mind that VA will recognize response commands (and confirmation shows up on the event log), but the flag keeps anything from actually being executed if you happened to say "yes" under other circumstances. The "full stop" coding at the end doesn't really apply to this example. I use it more extensively in other commands that save a multitude of variables based on user input. Basically if the user says "cancel" I want to undo anything that was set by the user prior to the "cancel" command as well as stop processing all VA commands. 

So try out the "Reset Game Data" command and see what you think. It sounds like some of what you need might benefit from more flexible VA "dictation" (check out the VA forums to find some posts that talk about the pros/cons to using pure dictation to retrieve user input). I built these commands before command-scoped variables were implemented, so there certainly are things I could do to clean up the code and trim the fat. The community may have more slick ways of achieving this, but it works for me!

Hopefully this helps get you started on some of the challenges you're aiming to tackle :)

Root Command = "Reset Game Data"
Code: [Select]
Set integer [input request] value to 1
Set integer [loop recognition counter] value to 1
Marker: Beginning
Set Text [answer] to [Not Set]
Set Text [question] to 'Are you sure you want to reset all data for the Mass Effect 3 profile?'
Set Text [response hint] to 'Example input is: YES, or, NO, or say CANCEL.'
Set Text [text hint] to 'Valid input: YES or NO. Or say CANCEL.'
Begin Integer Compare : [loop recognition counter] Is Less Than Or Equals 3
    Execute command, 'User Query' (and wait until it completes)
    Begin Text Compare : [answer] Equals 'Yes'
        Set integer [loop recognition counter] value to 1
        Clear saved data from profile : small int (condition), integer, text, true/false (boolean), decimal
        Do more stuff
        Write '[Purple] Data reset complete.' to log
    Else If Text Compare : [answer] Equals 'No'
        Say, 'Acknowledged, request cancelled. '  (and wait until it completes)
        Jump to Marker: End
    Else If Text Compare : [answer] Equals 'Cancel'
        Say, 'Request cancelled'  (and wait until it completes)
        Set integer [full stop] value to 1
        Jump to Marker: End
    Else
        Begin Integer Compare : [loop recognition counter] Is Less Than 3
            Say, 'Input not recognized. {TXT:response hint}. Please try again'  (and wait until it completes)
        End Condition
        Set integer [loop recognition counter] to [loop recognition counter] plus 1
    End Condition
Else
    Say, 'Input not recognized. Request not processed.'  (and wait until it completes)
    Set integer [full stop] value to 1
    Jump to Marker: End
End Condition

Marker: End
Set integer [answer] value to [Not Set]
Set integer [input request] value to [Not Set]
Begin Integer Compare : [full stop] Equals 1
    Set integer [full stop] value to [Not Set]
    Stop VoiceAttack command processing
End Condition

Query Command = "User Query"
Code: [Select]
Set integer [loop input counter] value to 1
Set integer [timer max] value to 5
Set integer [input request] value to 1
Marker: Beginning
Set Text [answer] to [Not Set]
Begin Integer Compare : [loop input counter] Is Less Than Or Equals 3
    Write '[Black] {TXT:question}' to log
    Say, '{TXT:question}'  (and wait until it completes)
    Set integer [timer] value to 0
    Write '[Pink] {TXT:text hint}' to log
    Write '[Black] Waiting for input' to log
    Start Loop While : [answer] Has Not Been Set
        Begin Integer Compare : [timer] Is Greater Than Or Equals [timer max]
            Begin Integer Compare : [loop input counter] Is Less Than Or Equals 2
                Say, 'No input recognized. {TXT:response hint}. Please try again'  (and wait until it completes)
            End Condition
            Set integer [loop input counter] to [loop input counter] plus 1
            Jump to Marker: Beginning
        End Condition
        Write '[Blank] {EXP:{INT:timer max}-{INT:timer}}' to log
        Pause 1 second
        Set integer [timer] to [timer] plus 1
    End Loop
    Set integer [loop input counter] value to 1
Else
    Say, 'No input recognized. Request not processed.'  (and wait until it completes)
    Stop VoiceAttack command processing
End Condition
Set integer [input request] value to [Not Set]

Response Command = "yes; no; cancel"
Code: [Select]
Begin Integer Compare : [input request] Equals 1
    Set Text [answer] to '{LASTSPOKENCMD}'
End Condition
« Last Edit: May 04, 2017, 09:49:24 AM by Exergist »

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4778
  • RTFM
VA loads the python script in the background and enters in $mortargrid and $targetgrid and runs the script
This is the difficult part; VoiceAttack doesn't run python scripts(directly), and the python script you're linking is designed for keyboard input

You could rewrite it as an inline C#/VB.NET function that uses VoiceAttack variables directly, that's probably the cleanest way of doing it.

Antaniserse

  • Global Moderator
  • Jr. Member
  • *****
  • Posts: 87
    • My VA plugins
This is the difficult part; VoiceAttack doesn't run python scripts(directly), and the python script you're linking is designed for keyboard input

You could rewrite it as an inline C#/VB.NET function that uses VoiceAttack variables directly, that's probably the cleanest way of doing it.
Agreed... that code needs to be drastically re-written anyway, since it is set to execute with a interactive command prompt, not as a fully automated script.

At that point, one might as well bite the bullet and convert it in .NET
"I am not perfect and neither was my career. In the end tennis is like life, messy."
Marat Safin

stoopidsxyflanders

  • Guest
It's a basic script so I'm sure I could convert it to .net pretty easily (I didn't write the script so it's not like I'm having to re-do anything). Is there any documentation available on how to run .net scripts through VA?

Antaniserse

  • Global Moderator
  • Jr. Member
  • *****
  • Posts: 87
    • My VA plugins
It's a basic script so I'm sure I could convert it to .net pretty easily (I didn't write the script so it's not like I'm having to re-do anything). Is there any documentation available on how to run .net scripts through VA?

It's just integrated in the software itself: when editing a command, choose "Inline function" from the action list and then simply write your code in C# or VB.NET... if things ever start to get a bit too complex, you may want to switch to a proper plugin (standard .NET DLL, could be done with any free edition of Visual Studio) for finer control and improved performances

More instructions are available in the usual VoiceAttack manual... page 73 and onward for the Inline functions, page 138 and onward for all the details regarding the objects accessible (all the "proxy" functions described for the plugins are valid also when coding inline)
"I am not perfect and neither was my career. In the end tennis is like life, messy."
Marat Safin