I've used states like this to run a similar process. Again, like Newgate said, it does depend on what the rest of the script is doing - for example, it may limit or even halt some of the things that Script 1 is currently doing.
The way that I worked it was:
Script 1 is running in given state. When it needs to pass information to Script 2, it stores the information that it needs to pass in global variables, then jumps to a new state that simply passes the information to Script 2 and waits for a response. When it gets the response, it jumps to a new state again that gets it back into the swing of processing whatever it needs to process.
Here are some example scripts (forgive my ineptitude - I'm still new to scripting myself!)
This would be Script 1:
// values that will be passed from this script out to Script 2
string vOutVariable1;
string vOutVariable2;
string vOutVariable3;
// values that will be returned back from Script 2
string vReturnedVariable1;
string vReturnedVariable2;
state Running
{
touch_start(integer vNumber) // or whatever event handler you are using
{
// doing whatever it needs to do, then it gets to the point where it needs to pass processing over to Script 2
// assign the values that you need to pass over to Script 2 into global string variables (typecasting to strings where needed)
vOutVariable1 = // whatever
vOutVariable2 = // whatever
vOutVariable3 = // whatever
state WaitingForResponse;
}
}
state WaitingForResponse
{
state_entry()
{
// send the info to Script 2 - 'Command1' should be a string of your choosing that Script 2 will recognize to know it's time to start processing
llMessageLinked(LINK_THIS, 0, "Command1~" + vOutVariable1 + "~" + vOutVariable2 + "~" + vOutVariable3, NULL_KEY);
}
link_message(integer vSender, integer vNumber, string vString, key vID)
{
// now this state just sits and waits until it hears back from Script 2 - it will recognize the message by 'Command2'
list vParameters = llParseStringKeepNulls(vString, ["~"], []);
if (llList2String(vParameters, 0) == "Command2")
{
vReturnedVariable1= llList2String(vParameters, 1);
vReturnedVariable2= llList2String(vParameters, 2);
state ContinueRunning;
}
}
}
state ContinueRunning
{
// put whatever code you want in here to run after you get the info back from Script 2
}
And this would be Script 2:
// values that will be passed into this script from Script 1
string vInVariable1;
string vInVariable2;
string vInVariable3;
// values that will be returned from this script back to Script 1
string vReturningVariable1;
string vReturningVariable2;
state Idle
{
link_message(integer vSender, integer vNumber, string vString, key vID)
{
// this state just sits and waits until it gets a message from Script 1 - it verifies it is the correct message by checking to see if it includes 'Command1'
list vParameters = llParseStringKeepNulls(vString, ["~"], []);
if (llList2String(vParameters, 0) == "Command1")
{
// if we got the right 'Command1', then split the message back into it's individual variables
// this is where we'd typecast back to the native variable format ie, if we were passing integers or vectors
vInVariable1 = llList2String(vParameters, 1);
vInVariable2 = llList2String(vParameters, 2);
vInVariable3 = llList2String(vParameters, 3);
state Processing;
}
}
}
state Processing
{
state_entry()
{
// do whatever you need to do in Script 2 here - this can be as simple or as complex as you need it
// when you're ready, assign the variables that you'll need to pass back to Script 1
vReturningVariable1 = // whatever
vReturningVariable2 = // whatever
// send the info back to Script 1
llMessageLinked(LINK_THIS, 0, "Command2~" + vReturningVariable1 + "~" + vReturningVariable2, NULL_KEY);
// go back to sitting around and waiting until Script 2 is needed again
state Idle
}
}
A few caveats here:
- a setup like this does halt script 1 entirely, it's going to send the message to script 2 and then do nothing but wait for an answer, you may be able to modify this, depending on the regular flow of control in Script 1
- Command1 and Command2 should simply be unique strings that you can define to make things easily understood by you. A setup like this allows for multiple scripts (like Script 3 and Script 4) to work in similar ways as Script 2, just listening for different commands
- if you want to pass integers or keys back and forth, you can pass one of each as the integer or key parameters in the llMessageLinked call. But for multiple integers or keys, or for other data types like vectors or rotations, cast them to strings and concatenate them, then split them and cast them back in the other script
- in Script 1, depending on the flow of control for your script, you may not need to have a ContinueRunning state; jumping back into Running is fine if that's what works. Similarly, in Script 2, you may not even need a Processing state, as you may be able to accomplish something very simple directly in the event handler in the Idle state and pass the llMessageLinked back right from there. Or, if Script 2 is very complex, it can have multiple states itself before passing the information back
- always make sure that both Script 1 and Script 2 are designed so that one is going to be in a state that has a link_message event handler that will respond when the other needs to call it. Otherwise, it's very easy for one of the scripts to hang and freeze
- this example is probably not memory efficient in a number of ways, and can be improved upon; for example, using something like a bunch of standard 4 digit codes as your 'commands' would allow the use of llGetSubString(vString, 0, 3) in your 'if' statements, instead of creating the list first and using the list memory if you don't need to.
For my own purposes, I was building an application that got very large and needed to be broken into a number of scripts. I developed a series of commands that each one could then use to call the others, and hand off processing in the application. I even used a system like this to define an external 'function' that was rather large and needed to be called from multiple scripts. Instead of including the 'function' in each script individually (taking up space and requiring multiple sources to edit if I need to change it) I put the 'function' in a seperate script, and used link messages like these to pass 'parameters' into the 'function' and have it process what it needs to and then return a value.