Sgqvur
FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
- Reaction score
- 62
First thing first, what does TOD mean?
Well it means Time Of Day (Off Topic: also it's the nickname of the former professional Warcraft 3 TFT player Tod (aka 4K.Tod)
who I think is now a decent SC2 player as well =), so yeah go Tod!), which can be tweaked in Warcraft 3 as I think we all know.
There are two functions below that act as a wrappers for the natives, that I think work more "intuitively".
Well you might ask, what's so bad about the natives? Well say for example that you need/want to set the TOD to 01:30.
You can do that with [ljass]SetFloatGameState(GAME_STATE_TIME_OF_DAY, 1.5)[/ljass]. See the "problem"? The second argument 1.5
is what the wrappers try to "fix". Now say you want to set the TOD to 01:47? Not so "intuitive" eh? So what the wrapper allows you
is to just use 1.47 as an argument or in general x.y (0 <= x <= 23, 0 <= y <= 59).
The two wrappers:
The second things are the functions split and join. These functions work in the following way:
split:
The split function takes a "pattern" argument and a string to split and returns an array
containing the substrings, I think an example might help to clarify things:
[ljass]string array sa = split(":", "a:b:c:d")[/ljass]
the result of the above line (which is not a valid [v]Jass[2], nor I think anything else for that matter)
simply sets (it creates a new array) the first element of sa to a, the second to b, etc. So the sa will look like:
---- 0 1 2 3
sa: |a|b|c|d|
join:
The join function does the opposite, it takes an array and a string parameter and it "fuses/glues/concatenates" the elements of
the array in to a string, ex:
[ljass]string s = join(".", ["the", "helper", "net"])[/ljass]
the result would be that s == "the.helper.net" (again the above line is not a valid [v]Jass[2])
Okay, but the problem with [v]Jass[2] is that functions can't take nor return arrays. So does that mean
that the split and join can't be used? Of course not. The workaround is to make them use implicit arrays,
not explicitly accept arrays as arguments.
So the following is a textmacro that allows users to make their own split/join functions that work
on a implicit array specified also in the textmacro arguments:
An example usage might be:
[ljass]//! runtextmacro SPLIT_JOIN("S", "split", "join")[/ljass]
[ljass]//! runtextmacro SPLIT_JOIN("S1", "split1", "join1")[/ljass]
I recommend short names for both the functions (you can call them whatever you like,
not just split/join) and the implicit array, which will make both using them easier and some folks
think scripts will run faster, which is rather curious (but it can reduce readability of course).
So what good are the split/join combo in the realm of [v]Jass[2]?
Well as you can find out in the attached map, they can be really, really helpful for handling commands by the player(s)/"learning" purposes.
I will try to give here an arguable senseless example that uses two splits.
Say you have a save/load code in your map, that uses the format [ljass][str:agi:int x:y:z i1:i2:i3:i4:i5:i6][/ljass],
and you want to "load/init" your hero struct with those values.
Lets assume we have 2 split functions called split (uses S[] as implicit array) and split1 (uses S1[] as implicit array)
if we call split(" ", player_inputed_string) then
S[0] will be "str:agi:int"
now if we split1(":", S[0]) we will have
S1[0] = "str"
S1[1] = "agi"
S1[2] = "int"
and we can now easily set those values to our struct.
The same goes for S[1] which is "x:y:z" and S[2] which is "i1:i2:...:i6"
So I think this demonstrates how useful splits can be.
But what about join(s)? Well join can be useful as well, but I really can't think of an even
arguably good example (other than just printing the contents of the implicit array) for it in [v]Jass[2],
this doesn't mean that some more creative folks won't find it useful of course.
And of course if more split(s) and join(s) are required then simply run another textmacro =)!
PS: the split function is just like the StringExploader(I might be wrong about the name) that Romek (I might be wrong again =))
had uploaded a while back, but I think it's name was Php inspired, and split/join are borrowed from Perl =)
(which are names that probably many other programming languages use [no, not that many other languages are called Perl but
functions with same/similar functionality are called the same [split/join] =)).
Well it means Time Of Day (Off Topic: also it's the nickname of the former professional Warcraft 3 TFT player Tod (aka 4K.Tod)
who I think is now a decent SC2 player as well =), so yeah go Tod!), which can be tweaked in Warcraft 3 as I think we all know.
There are two functions below that act as a wrappers for the natives, that I think work more "intuitively".
Well you might ask, what's so bad about the natives? Well say for example that you need/want to set the TOD to 01:30.
You can do that with [ljass]SetFloatGameState(GAME_STATE_TIME_OF_DAY, 1.5)[/ljass]. See the "problem"? The second argument 1.5
is what the wrappers try to "fix". Now say you want to set the TOD to 01:47? Not so "intuitive" eh? So what the wrapper allows you
is to just use 1.47 as an argument or in general x.y (0 <= x <= 23, 0 <= y <= 59).
The two wrappers:
JASS:
function settod takes real time returns nothing
local integer whole_part = R2I(time)
local real real_part = time - whole_part
set real_part = real_part / 60 * 100
call SetFloatGameState(GAME_STATE_TIME_OF_DAY, whole_part + real_part)
endfunction
function TriggerRegisterTODEvent takes trigger t, real time returns event
local integer whole_part = R2I(time)
local real real_part = time - whole_part
set real_part = real_part / 60 * 100
return TriggerRegisterGameStateEvent(t, GAME_STATE_TIME_OF_DAY, EQUAL, whole_part + real_part)
endfunction
// example usage:
// call settod(13.37)
// call TriggerRegisterTODEvent(t, 5.50)
The second things are the functions split and join. These functions work in the following way:
split:
The split function takes a "pattern" argument and a string to split and returns an array
containing the substrings, I think an example might help to clarify things:
[ljass]string array sa = split(":", "a:b:c:d")[/ljass]
the result of the above line (which is not a valid [v]Jass[2], nor I think anything else for that matter)
simply sets (it creates a new array) the first element of sa to a, the second to b, etc. So the sa will look like:
---- 0 1 2 3
sa: |a|b|c|d|
join:
The join function does the opposite, it takes an array and a string parameter and it "fuses/glues/concatenates" the elements of
the array in to a string, ex:
[ljass]string s = join(".", ["the", "helper", "net"])[/ljass]
the result would be that s == "the.helper.net" (again the above line is not a valid [v]Jass[2])
Okay, but the problem with [v]Jass[2] is that functions can't take nor return arrays. So does that mean
that the split and join can't be used? Of course not. The workaround is to make them use implicit arrays,
not explicitly accept arrays as arguments.
So the following is a textmacro that allows users to make their own split/join functions that work
on a implicit array specified also in the textmacro arguments:
JASS:
function index takes string source, string pattern, integer offset returns integer
local integer source_len = StringLength(source)
local integer pattern_len = StringLength(pattern)
local integer str_p = 0
if offset < 0 then
set str_p = source_len + offset
else
set str_p = str_p + offset
endif
loop
exitwhen str_p >= source_len - pattern_len + 1
if SubString(source, str_p, str_p + pattern_len) == pattern then
return str_p
endif
set str_p = str_p + 1
endloop
return -1
endfunction
//! textmacro SPLIT_JOIN takes ARRAY_NAME, SPLIT_NAME, JOIN_NAME
globals
string array $ARRAY_NAME$
integer $ARRAY_NAME$_size = 0
endglobals
function $SPLIT_NAME$ takes string pattern, string source returns nothing
local integer a = 0
local integer b = 0
set $ARRAY_NAME$_size = 0
if pattern != "" and pattern != null then
set b = index(source, pattern, a)
loop
exitwhen b < 0
set $ARRAY_NAME$[$ARRAY_NAME$_size] = SubString(source, a, b)
set $ARRAY_NAME$_size = $ARRAY_NAME$_size + 1
set a = b + 1
set b = index(source, pattern, a)
endloop
set $ARRAY_NAME$[$ARRAY_NAME$_size] = SubString(source, a, StringLength(source))
set $ARRAY_NAME$_size = $ARRAY_NAME$_size + 1
else
loop
exitwhen $ARRAY_NAME$_size >= StringLength(source)
set $ARRAY_NAME$[$ARRAY_NAME$_size] = SubString(source, $ARRAY_NAME$_size, $ARRAY_NAME$_size + 1)
set $ARRAY_NAME$_size = $ARRAY_NAME$_size + 1
endloop
endif
endfunction
function $JOIN_NAME$ takes string glue returns string
local string result = ""
local integer split_index = 0
loop
exitwhen split_index == $ARRAY_NAME$_size - 1
set result = result + $ARRAY_NAME$[split_index] + glue
rpu
set split_index = split_index + 1
endloop
set result = result + $ARRAY_NAME$[split_index]
return result
endfunction
//! endtextmacro
An example usage might be:
[ljass]//! runtextmacro SPLIT_JOIN("S", "split", "join")[/ljass]
[ljass]//! runtextmacro SPLIT_JOIN("S1", "split1", "join1")[/ljass]
I recommend short names for both the functions (you can call them whatever you like,
not just split/join) and the implicit array, which will make both using them easier and some folks
think scripts will run faster, which is rather curious (but it can reduce readability of course).
So what good are the split/join combo in the realm of [v]Jass[2]?
Well as you can find out in the attached map, they can be really, really helpful for handling commands by the player(s)/"learning" purposes.
I will try to give here an arguable senseless example that uses two splits.
Say you have a save/load code in your map, that uses the format [ljass][str:agi:int x:y:z i1:i2:i3:i4:i5:i6][/ljass],
and you want to "load/init" your hero struct with those values.
Lets assume we have 2 split functions called split (uses S[] as implicit array) and split1 (uses S1[] as implicit array)
if we call split(" ", player_inputed_string) then
S[0] will be "str:agi:int"
now if we split1(":", S[0]) we will have
S1[0] = "str"
S1[1] = "agi"
S1[2] = "int"
and we can now easily set those values to our struct.
The same goes for S[1] which is "x:y:z" and S[2] which is "i1:i2:...:i6"
So I think this demonstrates how useful splits can be.
But what about join(s)? Well join can be useful as well, but I really can't think of an even
arguably good example (other than just printing the contents of the implicit array) for it in [v]Jass[2],
this doesn't mean that some more creative folks won't find it useful of course.
And of course if more split(s) and join(s) are required then simply run another textmacro =)!
PS: the split function is just like the StringExploader(I might be wrong about the name) that Romek (I might be wrong again =))
had uploaded a while back, but I think it's name was Php inspired, and split/join are borrowed from Perl =)
(which are names that probably many other programming languages use [no, not that many other languages are called Perl but
functions with same/similar functionality are called the same [split/join] =)).