View Full Version : Time-parsing - need an efficient script
Fever
16-02-2004, 08:23 PM
Can someone post an example of an efficent time-parsing script?
What is time-parsing you ask??....my take on it is a quick double hit of a button which activates a script and allows alternate key strokes to be used by a predefined number of buttons.
I would like to use it to activate wingman commands when im in single player, dont need the multiplayer coms at that point but would like to make use of those same buttons.
Time-parsing in combination with the menu stepping script i saw in another thread would be cool.
Fever
MichaelCHProd
16-02-2004, 08:49 PM
Are you looking for a sub mode for only certain buttons?
I.E. When you press button 1 twice in a set period of time it will change the functions of buttons 3-6 to different commands.
Fever
16-02-2004, 09:28 PM
Yes! Or double press one of the buttons in the set of buttons i want to reprogram to enable the alternate commands. And of course double press that same button to return to "normal".
MichaelCHProd
16-02-2004, 09:58 PM
Ok tell me the keys you want and the actions to be taken in order.
Fever
16-02-2004, 10:12 PM
OK, but lets talk in general terms as i havent figured out everything i want to do yet. What i'd like is to have the top front hat on the ProThrottle be "remapped" to 4 new commands when that same hat "up" button is pressed twice quickly. Note this also remaps the "up" button to a new command as well. OK, now that we are in the "new map" for the hat a quick double press of the "up" hat button takes us back to the original 4 commands for the hat (all are macros by the way). I don't have my controllers in front of me to give you the button numbers but i think you get the idea.
Is that enough info??? You can make up macros ie 1... 2... 3... 4.., and CMS buttons.. ill change them later :).
Fever:
Here's an example from one of my scripts, where I set-up time-parsed functions on four keys that otherwise serve as shift keys:
// ================================================== ================================
// Time-Parsed Shift Keys
// Timers: d1-d8
// Bits: cms.b1-b2, cms.b58, cms.b61
// ================================================== ================================
// Zoom (FS Shift 1)
pulse(d1) = js1.b4;
timer(offdelay,d2,5) = d1 and not d2;
cms.b1 = d2 and not js1.b4;
// Target Reticle (FS Shift 2)
pulse(d3) = js1.b3;
timer(offdelay,d4,5) = d3 and not d4;
cms.b2 = d4 and not js1.b3;
// Time Compression (PT Shift 1)
pulse(d5) = js2.b4;
timer(offdelay,d6,5) = d5 and not d6;
cms.b61 = d6 and not js2.b4;
// ENTER (PT Shift 2)
pulse(d7) = js2.b3;
timer(offdelay,d8,5) = d7 and not d8;
cms.b58 = d8 and not js2.b3;
To give credit where credit is due, the time-parsing method employed in this script was devised by Bob Church. I use it all of the time and it works very well.
The time parsing works the same way in each of the four examples. Basically, what it does is sense a press of the time-parsed key and activate the time-parsed function if the key is released quickly enough. The offdelay timers (i.e., d2, d4, d6, and d8 in the script above) turn on when the key is pressed and stay on for "5" time units thereafter. If the key is released before the timer is turned off, the output (e.g., cms.b1, cms.b2, cms.b61, or cms.b58 in the script above) is turned on. You can make the time-parsing more or less time-sensitive by altering the offdelay persistence value (i.e., "5" in the script above).
I hope this helps.
- JNOV
Fever
17-02-2004, 02:44 AM
I've been staring at this for a while now and i think i understand whats going on (after reading the help files in CM3). This script will be useful in setting a state variable to "TRUE" that will allow my "new map" commands to be executed. Now i have a headache. Thanks for the help.
Fever
I think it's a little confusing because of the way that the offtimer and pulse timer work together. The pulse timer (e.g., d1) is true for exactly one program scan when you press the time-parsed button. So, one program scan after you press the button, it goes false and the offtimer starts. The offtimer stays on for a certain period of time (e.g., 5 "time units"), and if you let go before it turns off, the output expression will be true, because (using the first example in the script as a reference):
1. d2 is true, because the offtimer is still on
2. js1.b4 is false, because you've released the time-parsed button
3. not js1.b4 is true, because js1.b4 is false
4. d2 and not js1.b4 is true, because of 1-3 above
In my example, I've used the time-parsed output to turn on cms bits, which, in the GUI, I've mapped to useful game commands (e.g., toggle zoom). But you can use them for other purposes. In another script, I use two time-parsed inputs to sequence forward and backward, respectively, through a list of ten states, each of which represents one of ten possible zoom levels.
It's also more confusing than necessary because of the extra term in the timer line. To make it easier to understand, you can get rid of the second term after the equal sign, so that the expression becomes
timer(offdelay,d2,5) = d1;
That makes the off timer's (d2's) dependence on the pulse timer (d1) a little more obvious. The "and not d2" is a safety measure so that the off timer (d2) will not try to turn itself on if it's already on. It will probably work fine without this bit.
If you've got any questions, I'll do my best to help. Have fun!
- JNOV
MichaelCHProd
17-02-2004, 06:12 AM
I could not for the life of me remember where I put that. I spent all day looking for that script. :P
Thank You for picking up my slack JNOV <s>
Bob Church
17-02-2004, 07:38 AM
JNOV,
Since CM3 came out with the PERIOD timer, you can simplify that a little. It will essentially replace the PULSE/ONDELAY pair with a single timer:
timer( PERIOD, d1, 5 ) = js1.b2;
cms.b1 = d1 and not js1.b2;
It works the same as what you're doing, it just saves the pulse statement since the PERIOD timer runs whether the input stays closed or not.
- Bob
The StickWorks
http://www.stickworks.com
Fever
17-02-2004, 01:39 PM
Thanks Bob, that is a little more efficient. Now how to implement wingman commands in LOMAC using all this good stuff :). F1-F3 on one button, F4-F6 on another...... i wish there was a way to step up and down in the command menu :(.
Thanks, Bob! I've been using that script for so long that it never occurred to me to update it!
- JNOV
Bob Church
17-02-2004, 10:29 PM
Fever,
>> Thanks Bob, that is a little more efficient. Now how to implement wingman commands in LOMAC using all this good stuff . F1-F3 on one button, F4-F6 on another...... i wish there was a way to step up and down in the command menu. <<
The CMNOTE01.ZIP file I posted on the "Files" page over on my web site shows a way to generate a sequence of characters, one character per click, and it will reverse the order. Actually, it sequences bits, but then they can be assigned as CMS buttons and the characters generated up there. You might want to take a look, might be some help.
- Bob
The StickWorks
http://www.stickworks.com
Bob Church
17-02-2004, 10:41 PM
JNOV,
>> Thanks, Bob! I've been using that script for so long that it never occurred to me to update it! <<
You're welcome! Yeah, I know how it goes. When it's working I tend to just leave well enough alone, too. I think it may have been that very operation that caused me to put the PERIOD type into the CM in the first place, the extra PULSE seemed kind of messy.
- Bob
The StickWorks
http://www.stickworks.com
Fever
18-02-2004, 01:43 AM
Thanks again Bob (thanks for your help too JNOV). I'm pretty sure i know what i have to do now. It's going to be a complicated script but i like a challange :). I'll post it here after im done.
Basically a quick press of my normal "online" multiplayer comms button will activate an altered mode for a hat (which contains the chat button) and each of those buttons will be assigned 3 function commands (ie F1 F2 F3 on one button) for single player comms with AI wingmen. Quick presses of the individual buttons on the hat will generate the proper F key (one press = F1, 2 presses = F2, 3 quick presses = F3). The comms button will be used to exit the altered mode if no other button was pressed after entering the altered mode. This all sounds confusing but the menu structure in LOMAC is not setup for easy navigating using hat buttons :). The only thing you'll need to remember is which buttons send which F keys.. 1 button = F1-F3, the next button F4-F6, the next button F7-F9 and the comms button will get F11, F12 and a quick exit function. I think im possessed.
Fever
Fever
19-02-2004, 05:05 AM
Bob/Michael/JNOV
Do you guys see any glaring errors here? Almost got it to work but its not sending the F1-F3 keys right. I noticed you cant put a timer in an IF/THEN statement. Doesn't mention that in the help file, although the help file has been a very good reference.
Thanks for your time.
IF ( NOT B52 ) THEN //B52 will designate if we are in comms menu
SEQUENCE
CMS.B17=JS2.B9; //normal operation of hat ie ~, F7, F1, F12
CMS.B18=JS2.B10;
CMS.B19=JS2.B11;
CMS.B20=JS2.B12;
ENDSEQUENCE
ENDIF
// Look to see if comms has been activated (this happens with a quick press of B12 or "F12")
B99 = JS2.B12;
TIMER (PERIOD,D5,6) = B99; //Quick press timer for turning on comms menu
IF ( D5 AND NOT B99 AND NOT B52 ) THEN //Turn on comms mode if quick press detected on button F12 and we are not already in the comms menu
SEQUENCE
CMS.B14 = TRUE; //Open up the comms menu
B39 = FALSE; //Initialize button off
B50 = FALSE; //Make sure comms sent variable is set to FALSE
B52 = TRUE; //We are now in the comms menu
A9 = 0; //Set all button press counters to unpressed state
A10 = 0;
A11 = 0;
A12 = 0;
A19 = 0; //Button press indicators
A20 = 0;
A21 = 0;
A22 = 0;
ENDSEQUENCE
ENDIF
IF ( NOT B52 ) THEN
B51 = TRUE; //Prime inactivity timer
B53 = TRUE; //Prime button counting timer
ENDIF
TIMER (OFFDELAY,D6,100) = B51; //Initialize inactivity timer, if we are inactive for too long then we will exit the comms menu
IF ( B52 ) THEN //Comms menu interface activated
SEQUENCE
B53 = FALSE; //OK, let the comms menu control the timer now
B51 = D9; //Start overall comms menu inactivity timer when button counting timer goes FALSE
//Look for button presses on top front hat switch on joystick 2
B69 = JS2.B9; //Button 9 pressed
IF ( B69 AND NOT B39 ) THEN
SEQUENCE
A19 = A19 + 1;
B39 = TRUE; // We have pressed the button
ENDSEQUENCE
ELSE
SEQUENCE
IF (NOT B69 AND B39 ) THEN
SEQUENCE
A19 = 0; //Button no longer pressed
B39 = FALSE; //Button no longer pressed
ENDSEQUENCE
ENDIF
ENDSEQUENCE
ENDIF
B70 = JS2.B10; //Button 10 pressed
IF ( B70 ) THEN
A20 = A20 + 1; // We have pressed the button
ELSE
A20 = 0; //Button no longer pressed
ENDIF
B71 = JS2.B11; //Button 11 pressed
IF ( B71 ) THEN
A21 = A21 + 1; // We have pressed the button
ELSE
A21 = 0; //Button no longer pressed
ENDIF
B72 = JS2.B12; //Button 12 pressed
IF ( B72 ) THEN
A22 = A22 + 1; // We have pressed the button
ELSE
A22 = 0; //Button no longer pressed
ENDIF
ENDSEQUENCE
ENDIF
TIMER (OFFDELAY,D9,20) = B53 OR B69 OR B70 OR B71 OR B72; //Start timer for counting button presses, may have to setup individual timers for each button
IF ( B52 ) THEN //Comms menu interface activated
SEQUENCE
//Setup Menu Commands For Button 9
IF ( D9 AND [ A9 < 3 ]) THEN
SEQUENCE
IF ( [A19 == 1] ) THEN //Check to see if we should increment the counter (only count one button press though)
SEQUENCE
A9 = A9 + 1; //Increment A9
ENDSEQUENCE
ENDIF
ENDSEQUENCE
ELSE
SEQUENCE
IF ( [ A9 > 0 ] AND [ A10 == 0 ] AND [ A11 == 0 ] AND [ A12 == 0 ] ) THEN //Make sure no other buttons interupted selection
SEQUENCE
IF ( [ A9 == 1 ] ) THEN
SEQUENCE
B921 = TRUE;
A9 = 0; // Reset button presses number
B50 = TRUE; //Comms sent variable set to true
ENDSEQUENCE
ENDIF
IF ( [ A9 == 2 ] ) THEN
SEQUENCE
B922 = TRUE;
A9 = 0; // Reset button presses number
B50 = TRUE; //Comms sent variable set to true
ENDSEQUENCE
ENDIF
IF ( [ A9 == 3 ] ) THEN
SEQUENCE
B923 = TRUE;
A9 = 0; // Reset button presses number
B50 = TRUE; //Comms sent variable set to true
ENDSEQUENCE
ENDIF
ENDSEQUENCE
ELSE
SEQUENCE
DELAY (2);
A9 = 0; //A different button was pressed so we need to restart
A10 = 0;
A11 = 0;
A12 = 0;
ENDSEQUENCE
ENDIF
ENDSEQUENCE
ENDIF
//Setup Menu Commands For Button 10
//Setup Menu Commands For Button 11
//Setup Menu Commands For Button 12
ENDSEQUENCE
ENDIF
IF ( B921 ) THEN
SEQUENCE
CMS.B21 = TRUE;
DELAY ( 2 );
B921 = FALSE;
CMS.B21 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B922 ) THEN
SEQUENCE
CMS.B22 = TRUE;
DELAY ( 2 );
B922 = FALSE;
CMS.B22 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B923 ) THEN
SEQUENCE
CMS.B23 = TRUE;
DELAY ( 2 );
B923 = FALSE;
CMS.B23 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B52 AND NOT D6 ) THEN //If inactivity timer goes false then close command menu
SEQUENCE
CMS.B14 = FALSE; //Close the comms menu
B52 = FALSE; //We are no longer in the comms menu
ENDSEQUENCE
ENDIF
MichaelCHProd
19-02-2004, 07:34 AM
Oh boy... :blink:
I think I am going wait for Bob to look at this before I venture in.
Fever
19-02-2004, 03:00 PM
I could probably simplify the code a great deal with a little more practice but i'm not totally sure how all the commands work yet in terms of how the script proceeds after the command and how the keyboard recognizes the signals (ie the need for the delay command).
Also, it seemed the code behaved differently whether i had a B1 defined when im using CMS.B1 or whether i switched that B1 for a B69. Does the "B1" in CMS.B1 interfere with a stand alone B1 bit????????
i think i could simplify this statement with a wait command:
B70 = JS2.B10; //Button 10 pressed
IF ( B70 ) THEN
A20 = A20 + 1; // We have pressed the button
ELSE
A20 = 0; //Button no longer pressed
ENDIF
OK, Bob show me your magic tricks!!
Fever
19-02-2004, 06:59 PM
Im getting closer. F1, F2 and F3 are sent depending on how long i hold the button down (flick of button gets F1, a little longer gets F2...). Not what i want, i want the number of quick presses to determine what key to send. Looks like i need to add more delays in the script to slow things down. I'll attach my latest CMS file for those that are interested to look at.
Fever:
That's just about the most complicated script I've ever seen -- definitely a candidate for some of CM3's labeling capabilities, just so you can keep straight what represents what!
I've only a minute to look at your listing, but I've a couple of observations:
1. I don't think that many of the sequence/endsequence strutcures you've included are doing what you want (admittedly, I'm not sure what you want, but I can't see that they're accompishing anything). As far as I can tell, most of the one ones in your script are unnecessary. Normally, I use sequence structures when the timing between outputs is important (like you do at the very bottom where you actually generate the keypresses).
2. Based on your description of what you're seeing and from my brief look at the script, I'd bet that what's happening is that your button-press counter (A9) is being incremented multiple times while the button is held down. In other words, your timers are operating to increment the counter once every-so-often while the button is pressed. If so, what you might consider is tying the button presses to PULSE timers. PULSE timers are true for exactly one program scan when you press a button, so they would eliminate the problem of multiple counts per press.
Sorry I don't have more time right now to look at it. Good luck!
- JNOV
Fever
19-02-2004, 09:49 PM
Thanks for the input JNOV. I think i found the issue, i wasn't handling A19 well if it's value went over 1.
According to the HELP file in CM3 a PULSE command will flip a bit for one cycle when the button is pressed as well as when it's released... wouldn't that send 2 TRUE "commands" with one button plress/release?
I'll simplify the script with PULSE commands once i understand EXACTLY how they work.
Yes it's complicated, and i havent even added the functionality for the other 3 buttons yet :) but you can see the place holders in the script. I also have a few commands that arent in use that i will purge.
Bob Church
19-02-2004, 11:21 PM
You're right about the SEQUENCE/ENDSEQUENCE pairs, you don't need most of them. A SEQUENCE is only needed when you've got a DELAY, WAIT, or WHILE statement between them. Otherwise they just make things more complex and when you put an IF/ENDIF around them they may stall in mid-sequence. It's best to avoid that situation unless you're really sure what it is that it's going to do for you.
WRT the rest of it, I'm still trying to see your logic. It's sometimes hard to figure out what the other fellow was thinking when he wrote something. It's sometimes hard to figure out what I was thinking when I wrote something for that matter. :) take it this is trying to do what you described a few posts up-thread:
1. The hat normally sends four commands, one per position.
2. If you rapidly close one of the positions, it switches to a "mode" (not one of the CM modes) where you can click the hat 1, 2, or 3 times rapidly in any of the 4 positions and get one of three different commands.
3. A 3 rapid clicks on one of the positions (the one that switched modes in the first place) will put the hat back to the normal mode.
Is that right?
- Bob
The StickWorks
http://www.stickworks.com
Fever
20-02-2004, 12:39 AM
Got it working!!! You guys need to check this bad boy out! I simplified the script a little but it's still LONG.
OK, what the script does.
This is a script for LOMAC single player communications. It basically allows you to send F1-F12 and the "\" command menu key all from one hat.
Here's how it works.
The first "up" quick press of the top hat on the ProThrottle will send that top hat into an alternate mode specifically for single player comms to your wingman. I usually use this "up" hat button for TeamSpeak when playing online but in single player it's not needed. So i turned it into a "mode" key if you will for this particular hat.
Note holding down the "up" hat for more than 1/2 second will not trigger the mode and the hat will function normally. Basically if you are talking on line and using this "press to talk" button you wont be saying anything thats less than a 1/2 second long :).
OK, back to what the script does.
Now that we've done our flick of the button and the "\" command menu key has been sent we can navigate through the single player menus by clicking the hat buttons in a certain way.
If you want F1, then click the forward hat button once
If you want F2, then click the forward hat button twice
If you want F3, then click the forward hat button three times (quickly of course)
If you dont click fast enough the script will asume you've finished your selection and send the appropriate key.
OK, If you want F4-F6 the down hat button will do the work
If you want F7-F9 the back hat button will do the work
and if you want F10-F12 (F10 is actial a "\" command to exit the menu fast) then use the old trusty up hat button (the same one we quick clicked to get into this alternate hat mode"
Doing nothing for a period of time automatically exits you from the comand menu and the hat functions normally again :).
Of course, you have a lot of CMS buttons to program for the script to work but that should be obvious.
Any comments?
// Single Player Communications Menu
// Script for the single player communications menu in LOMAC, one hat control using virtual submode
// By: Mike Fiori
// Date:2/18/2004
IF ( NOT B52 ) THEN //B52 will designate if we are in comms menu
SEQUENCE
CMS.B17=JS2.B9; //normal operation of hat ie ~, F7, F1, F12
CMS.B18=JS2.B10;
CMS.B19=JS2.B11;
CMS.B20=JS2.B12;
ENDSEQUENCE
ENDIF
// Look to see if comms has been activated (this happens with a quick press of B12 or "F12")
B99 = JS2.B12;
TIMER (PERIOD,D5,6) = B99; //Quick press timer for turning on comms menu
IF ( D5 AND NOT B99 AND NOT B52 ) THEN //Turn on comms mode if quick press detected on button F12 and we are not already in the comms menu
SEQUENCE
B50 = FALSE; //Make sure comms sent variable is set to FALSE
A9 = 0; //Set all button press counters to unpressed state
A10 = 0;
A11 = 0;
A12 = 0;
A19 = 0; //Button press indicators
A20 = 0;
A21 = 0;
A22 = 0;
CMS.B14 = TRUE; //Open up the comms menu
DELAY (2); //Let things settle in before we change A states
CMS.B14 = FALSE;
B52 = TRUE; //We are now in the comms menu
ENDSEQUENCE
ENDIF
IF ( NOT B52 ) THEN
B51 = TRUE; //Prime inactivity timer
B53 = TRUE; //Prime button counting timer
ENDIF
TIMER (OFFDELAY,D6,100) = B51; //Initialize inactivity timer, if we are inactive for too long then we will exit the comms menu
IF ( B52 ) THEN //Comms menu interface activated
SEQUENCE
B53 = FALSE; //OK, let the comms menu control the timer now
B51 = D9; //Start overall comms menu inactivity timer when button counting timer goes FALSE
//Look for button presses on top front hat switch on joystick 2
B69 = JS2.B9; //Button 9 pressed
IF ( B69 ) THEN
A19 = A19 + 1;
ELSE
A19 = 0; //Button no longer pressed
ENDIF
B70 = JS2.B10; //Button 10 pressed
IF ( B70 ) THEN
A20 = A20 + 1; // We have pressed the button
ELSE
A20 = 0; //Button no longer pressed
ENDIF
B71 = JS2.B11; //Button 11 pressed
IF ( B71 ) THEN
A21 = A21 + 1; // We have pressed the button
ELSE
A21 = 0; //Button no longer pressed
ENDIF
B72 = JS2.B12; //Button 12 pressed
IF ( B72 ) THEN
A22 = A22 + 1; // We have pressed the button
ELSE
A22 = 0; //Button no longer pressed
ENDIF
ENDSEQUENCE
ENDIF
TIMER (OFFDELAY,D9,10) = ( B53 OR B69 OR B70 OR B71 OR B72 ); //Start timer for counting button presses, may have to setup individual timers for each button
IF ( B52 ) THEN //Comms menu interface activated
SEQUENCE
//Setup Menu Commands For Button 9
IF ( D9 AND [ A9 < 4 ]) THEN
SEQUENCE
IF ( [A19 == 1] ) THEN //Check to see if we should increment the counter (only count one button press though)
A9 = A9 + 1; //Increment A9
ENDIF
ENDSEQUENCE
ELSE
SEQUENCE
IF ( NOT D9 AND [ A19 == 0 ] AND [ A9 > 0 ] AND [ A10 == 0 ] AND [ A11 == 0 ] AND [ A12 == 0 ] ) THEN //Make sure no other buttons interupted selection
SEQUENCE
IF ( [ A9 == 1 ] ) THEN
SEQUENCE
B921 = TRUE;
DELAY (2); // Give A9 time before it's changed again
A9 = 0; // Reset button presses number
B50 = TRUE; //Comms sent variable set to true
ENDSEQUENCE
ENDIF
IF ( [ A9 == 2 ] ) THEN
SEQUENCE
B922 = TRUE;
DELAY (2); // Give A9 time before it's changed again
A9 = 0; // Reset button presses number
B50 = TRUE; //Comms sent variable set to true
ENDSEQUENCE
ENDIF
IF ( [ A9 == 3 ] ) THEN
SEQUENCE
B923 = TRUE;
DELAY (2); // Give A9 time before it's changed again
A9 = 0; // Reset button presses number
B50 = TRUE; //Comms sent variable set to true
ENDSEQUENCE
ENDIF
ENDSEQUENCE
ELSE
A9 = 0; //A different button was pressed so we need to restart
ENDIF
ENDSEQUENCE
ENDIF
//Setup Menu Commands For Button 10
IF ( D9 AND [ A10 < 4 ]) THEN
SEQUENCE
IF ( [A20 == 1] ) THEN //Check to see if we should increment the counter (only count one button press though)
A10 = A10 + 1; //Increment A10
ENDIF
ENDSEQUENCE
ELSE
SEQUENCE
IF ( NOT D9 AND [ A20 == 0 ] AND [ A9 == 0 ] AND [ A10 > 0 ] AND [ A11 == 0 ] AND [ A12 == 0 ] ) THEN //Make sure no other buttons interupted selection
SEQUENCE
IF ( [ A10 == 1 ] ) THEN
SEQUENCE
B924 = TRUE;
DELAY (2); // Give A10 time before it's changed again
A10 = 0; // Reset button presses number
B50 = TRUE; //Comms sent variable set to true
ENDSEQUENCE
ENDIF
IF ( [ A10 == 2 ] ) THEN
SEQUENCE
B925 = TRUE;
DELAY (2); // Give A10 time before it's changed again
A10 = 0; // Reset button presses number
B50 = TRUE; //Comms sent variable set to true
ENDSEQUENCE
ENDIF
IF ( [ A10 == 3 ] ) THEN
SEQUENCE
B926 = TRUE;
DELAY (2); // Give A10 time before it's changed again
A10 = 0; // Reset button presses number
B50 = TRUE; //Comms sent variable set to true
ENDSEQUENCE
ENDIF
ENDSEQUENCE
ELSE
A10 = 0;//A different button was pressed so we need to restart
ENDIF
ENDSEQUENCE
ENDIF
//Setup Menu Commands For Button 11
IF ( D9 AND [ A11 < 4 ]) THEN
SEQUENCE
IF ( [A21 == 1] ) THEN //Check to see if we should increment the counter (only count one button press though)
A11 = A11 + 1; //Increment A11
ENDIF
ENDSEQUENCE
ELSE
SEQUENCE
IF ( NOT D9 AND [ A21 == 0 ] AND [ A9 == 0 ] AND [ A10 == 0 ] AND [ A11 > 0 ] AND [ A12 == 0 ] ) THEN //Make sure no other buttons interupted selection
SEQUENCE
IF ( [ A11 == 1 ] ) THEN
SEQUENCE
B927 = TRUE;
DELAY (2); // Give A11 time before it's changed again
A11 = 0; // Reset button presses number
B50 = TRUE; //Comms sent variable set to true
ENDSEQUENCE
ENDIF
IF ( [ A11 == 2 ] ) THEN
SEQUENCE
B928 = TRUE;
DELAY (2); // Give A11 time before it's changed again
A11 = 0; // Reset button presses number
B50 = TRUE; //Comms sent variable set to true
ENDSEQUENCE
ENDIF
IF ( [ A11 == 3 ] ) THEN
SEQUENCE
B929 = TRUE;
DELAY (2); // Give A11 time before it's changed again
A11 = 0; // Reset button presses number
B50 = TRUE; //Comms sent variable set to true
ENDSEQUENCE
ENDIF
ENDSEQUENCE
ELSE
A11 = 0;//A different button was pressed so we need to restart
ENDIF
ENDSEQUENCE
ENDIF
//Setup Menu Commands For Button 12
IF ( D9 AND [ A12 < 4 ]) THEN
SEQUENCE
IF ( [A22 == 1] ) THEN //Check to see if we should increment the counter (only count one button press though)
A12 = A12 + 1; //Increment A12
ENDIF
ENDSEQUENCE
ELSE
SEQUENCE
IF ( NOT D9 AND [ A22 == 0 ] AND [ A9 == 0 ] AND [ A10 == 0 ] AND [ A11 == 0 ] AND [ A12 > 0 ] ) THEN //Make sure no other buttons interupted selection
SEQUENCE
IF ( [ A12 == 1 ] ) THEN
SEQUENCE
B930 = TRUE;
DELAY (2); // Give A12 time before it's changed again
A12 = 0; // Reset button presses number
B50 = TRUE; //Comms sent variable set to true
ENDSEQUENCE
ENDIF
IF ( [ A12 == 2 ] ) THEN
SEQUENCE
B931 = TRUE;
DELAY (2); // Give A12 time before it's changed again
A12 = 0; // Reset button presses number
B50 = TRUE; //Comms sent variable set to true
ENDSEQUENCE
ENDIF
IF ( [ A12 == 3 ] ) THEN
SEQUENCE
B932 = TRUE;
DELAY (2); // Give A9 time before it's changed again
A12 = 0; // Reset button presses number
B50 = TRUE; //Comms sent variable set to true
ENDSEQUENCE
ENDIF
ENDSEQUENCE
ELSE
A12 = 0; //A different button was pressed so we need to restart
ENDIF
ENDSEQUENCE
ENDIF
ENDSEQUENCE
ENDIF
IF ( B921 ) THEN
SEQUENCE
CMS.B21 = TRUE;
DELAY ( 2 );
B921 = FALSE;
CMS.B21 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B922 ) THEN
SEQUENCE
CMS.B22 = TRUE;
DELAY ( 2 );
B922 = FALSE;
CMS.B22 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B923 ) THEN
SEQUENCE
CMS.B23 = TRUE;
DELAY ( 2 );
B923 = FALSE;
CMS.B23 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B924 ) THEN
SEQUENCE
CMS.B24 = TRUE;
DELAY ( 2 );
B924 = FALSE;
CMS.B24 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B925 ) THEN
SEQUENCE
CMS.B25 = TRUE;
DELAY ( 2 );
B925 = FALSE;
CMS.B25 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B926 ) THEN
SEQUENCE
CMS.B26 = TRUE;
DELAY ( 2 );
B926 = FALSE;
CMS.B26 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B927 ) THEN
SEQUENCE
CMS.B27 = TRUE;
DELAY ( 2 );
B927 = FALSE;
CMS.B27 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B928 ) THEN
SEQUENCE
CMS.B28 = TRUE;
DELAY ( 2 );
B928 = FALSE;
CMS.B28 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B929 ) THEN
SEQUENCE
CMS.B29 = TRUE;
DELAY ( 2 );
B929 = FALSE;
CMS.B29 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B930 ) THEN
SEQUENCE
CMS.B30 = TRUE;
DELAY ( 2 );
B930 = FALSE;
CMS.B30 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B931 ) THEN
SEQUENCE
CMS.B31 = TRUE;
DELAY ( 2 );
B931 = FALSE;
CMS.B31 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B932 ) THEN
SEQUENCE
CMS.B32 = TRUE;
DELAY ( 2 );
B932 = FALSE;
CMS.B32 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B52 AND NOT D6 ) THEN //If inactivity timer goes false then close command menu
SEQUENCE
CMS.B14 = TRUE;
DELAY ( 2 );
CMS.B14 = FALSE; //Close the comms menu
B52 = FALSE; //We are no longer in the comms menu
ENDSEQUENCE
ENDIF
MichaelCHProd
20-02-2004, 01:12 AM
That is some wicked scripting. Nice work. :D
Very nice, Fever! I'd never thought of putting multiple time-parsed events on a single, unshifted key. (Frankly, I'm not sure I'm coordinated enough to get three quick clicks in on a regular basis, but two seems quite doable.) Your scheme is very efficient in terms of button space--throw in some shift keys and you've got a ridiculous number of functions on a single hat! You could probably program the entirety of the most complex single-player command tree on one hat.
I may just "adapt" it for my own use in the future! Thanks for the great idea!
- JNOV
Fever
20-02-2004, 01:32 PM
Thanks for the comments, it still needs a little tweeking on menu exit and resetting the count if a different key is pressed other than the one you started with and the quick press timer is still true (whew, takes a breath). I'll have it dialed in in a few days. In the mean time maybe some of the experts could help me get the code length down a bit. Maybe some nexted IF/THEN statements or some other PULSE tricks.
I have asked a few questions further up in the thread that i didnt see any answers too yet, please scan back if you have time.
Fever
Fever
20-02-2004, 11:37 PM
All done. Deleted all the SEQUENCEs i didnt need. Had to remove the auto exit because sometimes the menu exits for you. Hope this is useful to someone besides myself.
// Single Player Communications Menu
// Script for the single player communications menu in LOMAC, one hat control using virtual submode
// By: Mike Fiori
// Date:2/20/2004
IF ( NOT B52 ) THEN //B52 will designate if we are in comms menu
CMS.B17=JS2.B9; //normal operation of hat ie ~, F7, F1, F12
CMS.B18=JS2.B10;
CMS.B19=JS2.B11;
CMS.B20=JS2.B12;
ENDIF
// Look to see if comms has been activated (this happens with a quick press of B12 or "F12")
B99 = JS2.B12;
TIMER (PERIOD,D5,4) = B99; //Quick press timer for turning on comms menu
IF ( D5 AND NOT B99 AND NOT B52 ) THEN //Turn on comms mode if quick press detected on button F12 and we are not already in the comms menu
SEQUENCE
A9 = 0; //Set all button press counters to unpressed state
A10 = 0;
A11 = 0;
A12 = 0;
A19 = 0; //Button press indicators
A20 = 0;
A21 = 0;
A22 = 0;
A25 = 0; //Command interupt counters
A26 = 0;
A27 = 0;
A28 = 0;
A29 = 0; //Overall command interupt bit used to check for different button presses
CMS.B14 = TRUE; //Open up the comms menu
DELAY (2); //Let things settle in before we change A states
CMS.B14 = FALSE;
B52 = TRUE; //We are now in the comms menu
ENDSEQUENCE
ENDIF
IF ( NOT B52 ) THEN
//Disabled B51 = TRUE; //Prime inactivity timer
B53 = TRUE; //Prime button counting timer
ENDIF
// Disabled TIMER (OFFDELAY,D6,100) = B51; //Initialize inactivity timer, if we are inactive for too long then we will exit the comms menu
IF ( B52 ) THEN //Comms menu interface activated
B53 = FALSE; //OK, let the comms menu control the timer now
// Disabled B51 = D9; //Start overall comms menu inactivity timer when button counting timer goes FALSE
//Look for button presses on top front hat switch on joystick 2
IF ( JS2.B9 ) THEN //Button 9 pressed
A19 = A19 + 1;
ELSE
A19 = 0; //Button no longer pressed
ENDIF
IF ( JS2.B10 ) THEN //Button 10 pressed
A20 = A20 + 1; // We have pressed the button
ELSE
A20 = 0; //Button no longer pressed
ENDIF
IF ( JS2.B11 ) THEN //Button 11 pressed
A21 = A21 + 1; // We have pressed the button
ELSE
A21 = 0; //Button no longer pressed
ENDIF
IF ( JS2.B12 ) THEN //Button 12 pressed
A22 = A22 + 1; // We have pressed the button
ELSE
A22 = 0; //Button no longer pressed
ENDIF
ENDIF
TIMER (OFFDELAY,D9,15) = ( B53 OR JS2.B9 OR JS2.B10 OR JS2.B11 OR JS2.B12 ); //Start timer for counting button presses, may have to setup individual timers for each button
IF ( B52 ) THEN //Comms menu interface activated
//Setup Menu Commands For Button 9
IF ( D9 AND [ A9 < 4 ]) THEN
IF ( [A19 == 1] ) THEN //Check to see if we should increment the counter (only count one button press though)
A9 = A9 + 1; //Increment A9
ENDIF
IF ( [ A9 > 0 ] ) THEN //This is a bit for command interupt checking
A25 = 1; //maybe try pulse here
ENDIF
ELSE
IF ( NOT D9 AND [ A9 > 0 ] AND [ A10 == 0 ] AND [ A11 == 0 ] AND [ A12 == 0 ] ) THEN //Make sure no other buttons interupted selection
IF ( [ A9 == 1 ] ) THEN
B921 = TRUE;
A9 = 0; // Reset button presses number
ENDIF
IF ( [ A9 == 2 ] ) THEN
B922 = TRUE;
A9 = 0; // Reset button presses number
ENDIF
IF ( [ A9 == 3 ] ) THEN
B923 = TRUE;
A9 = 0; // Reset button presses number
ENDIF
A25 = 0;// A command was sent so we need to reset this interupt bit
A29 = 0;// Reset overall interupt bit
ELSE
A9 = 0; //A different button was pressed so we need to restart
ENDIF
ENDIF
//Setup Menu Commands For Button 10
IF ( D9 AND [ A10 < 4 ]) THEN
IF ( [A20 == 1] ) THEN //Check to see if we should increment the counter (only count one button press though)
A10 = A10 + 1; //Increment A10
ENDIF
IF ( [ A10 > 0 ] ) THEN //This is a bit for command interupt checking
A26 = 1;
ENDIF
ELSE
IF ( NOT D9 AND [ A9 == 0 ] AND [ A10 > 0 ] AND [ A11 == 0 ] AND [ A12 == 0 ] ) THEN //Make sure no other buttons interupted selection
IF ( [ A10 == 1 ] ) THEN
B924 = TRUE;
A10 = 0; // Reset button presses number
ENDIF
IF ( [ A10 == 2 ] ) THEN
B925 = TRUE;
A10 = 0; // Reset button presses number
ENDIF
IF ( [ A10 == 3 ] ) THEN
B926 = TRUE;
A10 = 0; // Reset button presses number
ENDIF
A26 = 0;// A command was sent so we need to reset this interupt bit
A29 = 0;// Reset overall interupt bit
ELSE
A10 = 0;//A different button was pressed so we need to restart
ENDIF
ENDIF
//Setup Menu Commands For Button 11
IF ( D9 AND [ A11 < 4 ]) THEN
IF ( [A21 == 1] ) THEN //Check to see if we should increment the counter (only count one button press though)
A11 = A11 + 1; //Increment A11
ENDIF
IF ( [ A11 > 0 ] ) THEN //This is a bit for command interupt checking
A27 = 1;
ENDIF
ELSE
IF ( NOT D9 AND [ A9 == 0 ] AND [ A10 == 0 ] AND [ A11 > 0 ] AND [ A12 == 0 ] ) THEN //Make sure no other buttons interupted selection
IF ( [ A11 == 1 ] ) THEN
B927 = TRUE;
A11 = 0; // Reset button presses number
ENDIF
IF ( [ A11 == 2 ] ) THEN
B928 = TRUE;
A11 = 0; // Reset button presses number
ENDIF
IF ( [ A11 == 3 ] ) THEN
B929 = TRUE;
A11 = 0; // Reset button presses number
ENDIF
A27 = 0;// A command was sent so we need to reset this interupt bit
A29 = 0;// Reset overall interupt bit
ELSE
A11 = 0;//A different button was pressed so we need to reset the button press count
ENDIF
ENDIF
//Setup Menu Commands For Button 12
IF ( D9 AND [ A12 < 4 ]) THEN
IF ( [A22 == 1] ) THEN //Check to see if we should increment the counter (only count one button press though)
A12 = A12 + 1; //Increment A12
ENDIF
IF ( [ A12 > 0 ] ) THEN //This is a bit for command interupt checking
A28 = 1;
ENDIF
ELSE
IF ( NOT D9 AND [ A9 == 0 ] AND [ A10 == 0 ] AND [ A11 == 0 ] AND [ A12 > 0 ] ) THEN //Make sure no other buttons interupted selection
IF ( [ A12 == 1 ] ) THEN
B930 = TRUE;
A12 = 0; // Reset button presses number
ENDIF
IF ( [ A12 == 2 ] ) THEN
B931 = TRUE;
A12 = 0; // Reset button presses number
ENDIF
IF ( [ A12 == 3 ] ) THEN
B932 = TRUE;
A12 = 0; // Reset button presses number
ENDIF
A28 = 0;// A command was sent so we need to reset this interupt bit
A29 = 0;// Reset overall interupt bit
ELSE
A12 = 0;//A different button was pressed so we need to reset the button press count
ENDIF
ENDIF
ENDIF
//Start the interupt bit if a button was pressed
IF ( NOT [ ( A25 + A26 + A27 + A28 ) == 0 ] ) THEN
A29 = 1;
ENDIF
//Check to see if 2 differenet buttons were pressed
IF ( NOT [ A29 == ( A25 + A26 + A27 + A28 ) ] ) THEN
A9 = 0; //OK, A command was interupted with a different button press so reset everything
A10 = 0;
A11 = 0;
A12 = 0;
A25 = 0;
A26 = 0;
A27 = 0;
A28 = 0;
A29 = 0;
ENDIF
IF ( B921 ) THEN
SEQUENCE
CMS.B21 = TRUE;
DELAY ( 2 );
CMS.B21 = FALSE;
B921 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B922 ) THEN
SEQUENCE
CMS.B22 = TRUE;
DELAY ( 2 );
CMS.B22 = FALSE;
B922 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B923 ) THEN
SEQUENCE
CMS.B23 = TRUE;
DELAY ( 2 );
CMS.B23 = FALSE;
B923 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B924 ) THEN
SEQUENCE
CMS.B24 = TRUE;
DELAY ( 2 );
CMS.B24 = FALSE;
B924 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B925 ) THEN
SEQUENCE
CMS.B25 = TRUE;
DELAY ( 2 );
CMS.B25 = FALSE;
B925 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B926 ) THEN
SEQUENCE
CMS.B26 = TRUE;
DELAY ( 2 );
CMS.B26 = FALSE;
B926 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B927 ) THEN
SEQUENCE
CMS.B27 = TRUE;
DELAY ( 2 );
CMS.B27 = FALSE;
B927 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B928 ) THEN
SEQUENCE
CMS.B28 = TRUE;
DELAY ( 2 );
CMS.B28 = FALSE;
B928 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B929 ) THEN
SEQUENCE
CMS.B29 = TRUE;
DELAY ( 2 );
CMS.B29 = FALSE;
B929 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B930 ) THEN
SEQUENCE
CMS.B30 = TRUE;
DELAY ( 2 );
CMS.B30 = FALSE;
B930 = FALSE;
B52 = FALSE; //We are no longer in the comms menu
ENDSEQUENCE
ENDIF
IF ( B931 ) THEN
SEQUENCE
CMS.B31 = TRUE;
DELAY ( 2 );
CMS.B31 = FALSE;
B931 = FALSE;
ENDSEQUENCE
ENDIF
IF ( B932 ) THEN
SEQUENCE
CMS.B32 = TRUE;
DELAY ( 2 );
CMS.B32 = FALSE;
B932 = FALSE;
ENDSEQUENCE
ENDIF
Fever
21-02-2004, 04:59 PM
New and improved!! Final version.
Fever
21-02-2004, 06:52 PM
OK :) final final version. Because LOMAC exits the comms menu automatically after a command is sent you have to "exit" the script so the hat returns to normal. I do this by quick clicking my shift button on my joystick (JS1.B6). If no command is sent and you are just browsing the command menu and you exit with F12 or "\" (3 and one quick press on the up hat button) then you dont need to hit the shift button. This is not for your average gamer, if the LOMAC command menu was set up better then the script would be much simpler. ENJOY!!
Bob Church
22-02-2004, 07:12 AM
The little zip that's attached to this has a MAP and CMS file in it that does something similar to what yours does. Basically, you can click Hat 1 one, two, or three times in any direction and get one of 12 commands (currently "a" through "l") preceded by a "/" character. If you hold the hat in one position for a longer time, you'll get a "w", "x", "y", or "z", corresponding to the normal commands. There are some simplifications and so some differences, though.
Only the direction of the last hat click makes any difference in the message. Other clicks can go any direction at all. For example, if the 3rd command (3 clicks) on Hat 1 Up were what you wanted to send, the first two clicks could be Hat 1 Left and Hat 1 Right, it wouldn't matter so long as the last click is Hat 1 Up. It's a simplification in that it lets the script watch the hat center button (js1.b21) and saves having to check all four directions since it doesn't really care which way it went except on the last click and that's recorded elsewhere.
Another simplification (not always usable) is that it doesn't use CMS.Bx outputs and you don't have to deal with those each time. Instead it converts the click count and direction into a number between 0 and 15, then multiplies and offsets that to produce one of 16 values between 0 and 255. That value is passed to CMS.A1 which is programmed with a "Position" statement that has command characters for the 16 positions that the script will produce. The value passed from the CMS file ends up selecting which one of them gets sent and the Position statement takes care of the rest.
Anyway, the CMS file ends up only being about 70 lines of actual code. I don't have LOMAC so it's just sort of an academic exercise here, I don't know if it will do everything you need done, but I thought some of it might be interesting. The map is set up for just a FighterStick, run it in the KeyTest utility and you can see everything that it does.
- Bob
The StickWorks
http://www.stickworks.com
Fever
22-02-2004, 03:43 PM
Thanks Bob. I downloaded your script and will check it out this week. I really like the idea of using positional keys on an axis and the "last" click direction being important as well.
Could you answer this question for me??
According to the HELP file in CM3 a PULSE command will flip a bit for one cycle when the button is pressed as well as when it's released... wouldn't that send 2 TRUE "commands" with one button plress/release?
Bob Church
22-02-2004, 05:04 PM
I saw you(?) mention the PULSE thing the other day and meant to respond then. It only changes state when it goes to TRUE, not when it goes to FALSE. It automatically turns FALSE after one loop regardless of the state of the input. I went back and looked at the Users' Guide and that's what it says, too, but then it may just be a case of me knowing what I meant. :) Which part seems to indicate that it flips on both transitions?
WRT the Position thing handling the characters, I thought it was kind of a neat way to handle it too. I'd thought earlier that it would be possible to control an axis in the script and then program it up in the GUI but I'd never really had occasion to do it. Anyway, maybe it'll simplify it a bit.
- Bob
The StickWorks
http://www.stickworks.com
Fever
22-02-2004, 09:08 PM
Pulse Device
The sixth type of device is the "Pulse" device. It sets it's Device Variable TRUE when it's input turns TRUE. On the next loop through the script, the Device Variable is set FALSE and will remain FALSE until the input goes FALSE and then turns TRUE again.
I copied this from the help section. I see what you are saying now. I took the last section of the last sentence (turns TRUE again) to mean it affected the device variable in the beginning of the sentence. You of course were referring to the input.
We are on the same page now :).
Thanks for replying.
Bob Church
23-02-2004, 12:25 AM
>> I took the last section of the last sentence (turns TRUE again) to mean it affected the device variable in the beginning of the sentence. <<
Ah. Yes, I see what you mean, it is kind of ambiguously stated. I'll clarify it a bit for the next go-round.
Thanks!
- Bob
The StickWorks
http://www.stickworks.com
vBulletin® v3.7.2, Copyright ©2000-2009, Jelsoft Enterprises Ltd.