Your questions are about variable scope in general. I will offer my opinion (take it with a grain of salt...), expand on options that are available and show an example to define some of it. It should help you learn more about what the language options are and what the technical terms are for you to read about in the documentation.
For your first examples, when the code is in ThirdSub and calls FourthSub, now returns to ThirdSub... both %1 and %2 are the same thing. Yikes!
So I would avoid that kind of construct, because eventually you will write something complex enough that it will betray you.In your second examples, you are using a global variable %neededJINDEX. This is very common in most scripts and we all do it all the time. It is not reusable code because of the variable scope violation.
There are about 5 categories of variables in Easyuo.
1)
standard variables (%myvar, %yourvar - or whatever you wish to name it) which have global scope in the current script, but not in scripts running in parallel tabs.
2)
variables passed on call/gosub statements (%0, %1, %2, etc (I shorthand refer to these as %#, but that isn't official) these are set with the call/gosub statement behind the scenes - so it is easy to insert code in the future that will cause relying on these to break)
3)
registry written variables prefixed with '*' (*myvar, *yourvar, etc.) - sometimes these are called persistent or global. There are a few library routines available to read and write these. I would recommend the one that TrailMyx wrote, because when well planned out it is easier to follow.
4)
namespace variables that are local (only available in the name space in the current script) are used to define more restrictive scope
5)
namespace variables that are global (available to any script in any tab of the current Easyuo instance... when in that namespace)
My personal experiences are to not rely on the value of %0, %1, %2, etc variables other than in 2 places:
- Immediately at the start of a sub or called routine.
- Immediately after the return of a sub or exited routine, when the sub needs to return more than 1 value (1 value can be returned with the return statement - which populates #RESULT) and I usurped some %# variable(s). I have done that in ad hoc code that I consider temporary, but it's not a method for general programming structure. There are more reliable methods available which I would recommend (namespace local/namespace copy).
TrailMyx mentioned they are 'regular variables' meaning you can set and use these, but they come with the caveat that the next gosub/call may overwrite your values.
%0 is the number of parameters passed with the most recent gosub/call statement. It is overwritten with each gosub/call statement, so it is only valid at the start of the sub/library.
So the proper way to validate that your %# variables is to test how many parameters were passed into this subroutine or library by testing %0. If %0 = 0 ... no parameters were passed. If %0 = 3 - it means the optional parameter you coded for %4 was not passed and you should be supplying a default value at the beginning of your subroutine.

If you want to protect your subroutine/library local variables, then you want to look at namespace commands. Namespace variables have the prefix: ! (!myvar, !yourvar, etc.)
gosub setup
gosub main %characterdata1 %characterdata2 %characterdata3
halt
sub main
namespace push
namespace local main
if %0 > 0
set !chard1 %1
if %0 > 1
set !chard2 %2
if %0 > 2
set !chard3 %3
else
set !chard3 defaultvalue
while %end_condition = #false
{
; do work
gosub Process1 !chard3
}
namepace pop
return
sub setup
; here define initialization or character specific data
set %characterdata1 blah
set %characterdata2 yes
set %characterdata3 42
return
sub Process1
namespace push ; preserve the former namespace so we can return to it later
namespace local Process1
if %0 > 0
set !chard1 %1 ; This chard1 is isolated from the !chard1 in the sub main
else
set !chard1 some_default_value ; This chard1 is isolated from the !chard1 in the sub main
; do work
namespace pop ; we are returning the former namespace that was in effect before the last namespace push command
return
So the use of namespace can allow you to reuse the variable name !chard1 in a different namespace and it won't overwrite any other namespace that has a variable with seemingly the same name of !chard1.
In the namespace, the variable is prefixed with other variable name stuff that keeps it in this semi-private scope.
When coding for namespace variables, and you are trying to debug a situation - never underestimate the value of knowing what your present namespace is via the variables
#NSNAME and
#NSTYPE. Paying attention to those variables helps to keep scope issues sanely manageable.
%# variables are constantly overwritten by gosub/call statements... hence not reliable other than at the start of the routine. Technically you could set a value to pass back using those. It is rarely useful to do that. Instead use the namespace copy commands. You will thank yourself later for having learned how to do that and for keeping your coding style consistent.

When using %# variables for passed parameters, always combine these with a test of %0 so you know if the %# variable you wish to take your value from really was just passed and not left over from some earlier gosub/call to a different routine.
When it comes to any programming, most often there are options for how to get to the desired result. Hopefully this gives you a little more background on what options are available.
Gaderian