• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • ✅ Time to vote for the top 3 models! The POLL for Hive's 6th HD Modeling Contest: Mechanical is now open! 📅 Poll close on July 16, 2024! 🔗 Cast your vote now!

Small Code Snippets

Level 31
Joined
Jul 10, 2007
Messages
6,306
JASS:
library SphericalProjection /* v1.0.0.1
*************************************************************************************
*
*   */uses/*
*   
*       */ AutoFly /*       hiveworkshop.com/forums/submissions-414/autofly-unitindexer-version-195563/
*
************************************************************************************
*
*   function SphericalProjection takes real x, real y, real z, real facing, verticalFacing, unit whichUnit, real distance, real theta, real phi returns nothing
*       -   x,y,z,facing,verticalFacing     source position. Vertical facing is z facing of unit, normally 0.
*       -   whichUnit                       unit to project
*       -   distance                        distance from position
*       -   theta                           x,y angle, 0 radians would be directly in front
*       -   phi                             z angle, 0 radians would be flat, pi/2 directly above, 
*       -                                   -pi/2 directly below
*
************************************************************************************/
function SphericalProjection takes real x, real y, real z, real f, real vf, unit u, real d, real t, real p returns nothing
    set t=t+f
    set f=d*Sin(p+vf)
    call SetUnitX(u,Cos(t)*f)
    call SetUnitY(u,Sin(t)*f)
    call SetUnitFlyHeight(u,d*Cos(p+vf),10000)
endfunction
endlibrary
 
Last edited:
JASS:
/*******************************************
*   Clock
*   v1.0.0.0
*   Magtheridon96
*
*   - A clock system that stores hours, minutes and seconds.
*
*   API:
*   ----
*
*       - function GetGameSeconds takes nothing returns integer
*       - function GetGameMinutes takes nothing returns integer
*       - function GetGameHours takes nothing returns integer
*
*       - function GetGameTimeString takes nothing returns string
*           - Returns the game-time string formatted: HH:MM:SS
*
*******************************************/
library Clock
    
    private struct Clock extends array
        
        static integer hours = 0
        static integer minutes = 0
        static integer seconds = 0
        
        static method buffer takes nothing returns nothing
            set seconds = seconds + 1
            if seconds == 60 then
                set seconds = 0
                set minutes = minutes + 1
                if minutes == 60
                    set minutes = 0
                    set hours = hours + 1
                endif
            endif
        endmethod

        private static method onInit takes nothing returns nothing
            call TimerStart(CreateTimer(), 1, true, function thistype.buffer)
        endmethod
    endstruct
    
    function GetGameSeconds takes nothing returns integer
        return Clock.seconds
    endfunction
    function GetGameMinutes takes nothing returns integer
        return Clock.minutes
    endfunction
    function GetGameHours takes nothing returns integer
        return Clock.hours
    endfunction
    function GetGameTimeString takes nothing returns string
        local string t = I2S(Clock.seconds)
        if Clock.seconds <= 9 then
            set t = "0" + t
        endif
        set t = I2S(Clock.minutes) + ":" + t
        if Clock.minutes <= 9 then
            set t = "0" + t
        endif
        set t = I2S(Clock.hours) + ":" + t
        if Clock.hours <= 9 then
            set t = "0" + t
        endif
        return t
    endfunction
endlibrary

I think it's pretty good :)

edit
- Made the struct extend an array and removed the module initializer + changed the variable names and the documentation.

Oh and you shouldn't be using this, you should be using this: http://www.hiveworkshop.com/forums/submissions-414/system-elapsedgametime-209231/
 
Last edited:
Nestharus' AddCommas significantly optimized:

JASS:
function AddCommas takes integer i returns string
    local string read = I2S(i)
    local string val = ""
    local integer pos = StringLength(read)
    loop
        set pos = pos - 3
        if pos < 0 then
            set val = SubString(read, 0, pos + 3) + val
            exitwhen true
        endif
        set val = "," + SubString(read, pos, pos + 3) + val
    endloop
    if SubString(val, 0, 1) == "," then
        return SubString(val, 1, StringLength(val))
    elseif SubString(val, 0, 2) == "-," then
        return "-" + SubString(val, 2, StringLength(val))
    endif
    return val
endfunction

To contrast:

JASS:
function AddCommas takes integer n returns string
    local integer m = 0
    local string s = ""
    local boolean b = false
    if (n < 0) then
        set n = -n
        set b = true
    endif
    loop
        exitwhen n == 0
        if (m > 0) then
            set s = "," + s
        endif
        set m = n
        set n = n/1000
        set m = m-n*1000
        if (n > 0) then
            if (m < 10) then
                set s = "00" + I2S(m) + s
            elseif (m < 100) then
                set s = "0" + I2S(m) + s
            else
                set s = I2S(m) + s
            endif
            set m = 1
        else
            set s = I2S(m) + s
            set m = 0
        endif
    endloop
    if (s == "") then
        return "0"
    endif
    if (b) then
        set s = "-" + s
    endif
    return s
endfunction
 
Last edited:
Level 17
Joined
Apr 27, 2008
Messages
2,455
Hmm, i would say that is slower because of SubString and StringLength and string concatenation.
A such function is not supposed to be used in heavy loop or rapid timers though, so that wouldn't matter so much.

Even if i hate the habit of Nestharus (use short names for variables because of speed freak), i would prefer his code, just because the way how string are handled in jass, the less you use, the best it is.
 
I have tested this plenty in-game. It does not bug at all :)

Also, it is heavily faster. Nestharus uses lots of math on top of concatenation, whereas this uses far fewer operations & lines to achieve the same end-result.

This also uses fewer loops. Nestharus runs it all char-by-char and this handles everything in blocks of three at a time.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
You can't use it to optimize the map's script since a good portion of maps can't use it to optimize their scripts >.>.

It'd be a pretty fail test since it wouldn't be the case in an actual map =P.

Just make ur var names 1 char each =D

edit
mine could be optimized a little
JASS:
function AddCommas takes integer n returns string
    local integer m = 0
    local string s = ""
    local boolean b = false
    if (n < 0) then
        set n = -n
        set b = true
    endif
    loop
        exitwhen n == 0
        if (m > 0) then
            set s = "," + s
        endif
        set m = n
        set n = n/1000
        set m = m-n*1000
        if (n > 0) then
            if (m < 10) then
                set s = "00" + I2S(m) + s
            elseif (m < 100) then
                set s = "0" + I2S(m) + s
            else
                set s = I2S(m) + s
            endif
        else
            set s = I2S(m) + s
        endif
    endloop
    if (s == "") then
        return "0"
    endif
    if (b) then
        set s = "-" + s
    endif
    return s
endfunction
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
You can't use it to optimize the map's script since a good portion of maps can't use it to optimize their scripts >.>.

It'd be a pretty fail test since it wouldn't be the case in an actual map =P.

Just make ur var names 1 char each =D

"a good portion of maps" seems far away from the truth, i guess only few (including yours).
Plus for this test it's perfectly possible.

Also, instead of keeping complaining about it, what about making a new one ? (you don't really need a GUI and all the wc3mapoptimizer stuff)
 
Ran some tests. The results were surprisingly close - it seemed Nestharus' script was a tiny bit faster, but then I shortened the variable names in my script and now mine is consistently a little bit faster.

The above results were when I passed the value 1,000,000,000.

When I passed the value as a negative number (-1,000,000,000) my script was at least 10-15% faster.

Tests:

JASS:
globals
    integer loopint = 0
endglobals

function AddCommas takes integer i returns string
    local string r = I2S(i)
    local string s = ""
    local integer p = StringLength(r)
    loop
        set p = p - 3
        if p < 0 then
            set s = SubString(r, 0, p + 3) + s
            if SubString(s, 0, 1) == "," then
                return SubString(s, 1, StringLength(s))
            elseif SubString(s, 0, 2) == "-," then
                return "-" + SubString(s, 2, StringLength(s))
            endif
            return s
        endif
        set s = "," + SubString(r, p, p + 3) + s
    endloop
    return "" //Parser thinks a return is missing -_-
endfunction

/*
function AddCommas takes integer n returns string
    local integer m = 0
    local string s = ""
    local boolean b = false
    if (n < 0) then
        set n = -n
        set b = true
    endif
    loop
        exitwhen n == 0
        if (m > 0) then
            set s = "," + s
        endif
        set m = n
        set n = n/1000
        set m = m-n*1000
        if (n > 0) then
            if (m < 10) then
                set s = "00" + I2S(m) + s
            elseif (m < 100) then
                set s = "0" + I2S(m) + s
            else
                set s = I2S(m) + s
            endif
        else
            set s = I2S(m) + s
        endif
    endloop
    if (s == "") then
        return "0"
    endif
    if (b) then
        set s = "-" + s
    endif
    return s
endfunction
*/
function go takes nothing returns nothing
    local integer i = 200
    loop
        call AddCommas(-1000000000)
        set i = i - 1
        exitwhen i == 0
    endloop
    set loopint = loopint + 1
    call DisplayTimedTextToPlayer(GetLocalPlayer(), 0,0,60,I2S(loopint))
    if loopint == 32 then
        set loopint = 0
    endif
endfunction

function InitTrig_Untitled_Trigger_001 takes nothing returns nothing
    call TimerStart(CreateTimer(), 0.03125, true, function go)
endfunction
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Ahem, Bribe, yours leaks way, way more strings....

I just tested it and after like 1.5 seconds using Troll-Brain's idea of a changing variable, yours went down to <1 fps. It took mine like 25 seconds to get down to 3fps >.>.

edit
for constant, Bribe is right that his is faster, but it again leaks masses of strings compared to mine.

I think the string leaks here are a bigger issue than speed.

edit
updated

JASS:
function AddCommas takes integer n returns string
    local integer m = 0
    local string s = ""
    local boolean b = false
    if (n == 0) then
        return "0"
    elseif (n < 0) then
        set n = -n
        set b = true
    endif
    loop
        set m = n
        set n = n/1000
        set m = m-n*1000
        if (n > 0) then
            if (m < 10) then
                set s = ",00" + I2S(m) + s
            elseif (m < 100) then
                set s = ",0" + I2S(m) + s
            else
                set s = "," + I2S(m) + s
            endif
        elseif (b) then
            return "-" + I2S(m) + s
        else
            return I2S(m) + s
        endif
    endloop
    return ""
endfunction

Mine is now consistently faster than Bribe's + leaks way less (tested).

Updated the snippet post as well

gg

edit
1 minute 43 seconds on new version to get to 3 fps.

Case closed.
 
Last edited:
See what happens when you challenge Nestharus? He finds a way to make his script even better, building the best possible resource. Win/win situation ^^

And he's right with the string leaks, this build won't leak nearly as much as mine! So I guess this proves that strings are still leaking even after the return bug was fixed. Why is WarCraft III still caching strings to that table when it's 100% useless now?
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Why is WarCraft III still caching strings to that table when it's 100% useless now?

They follow Murphy's law when they add/revome jass stuff in a patch.

Also since the begin i couldn't find about any really usefull case where typecasting string to integer to get the string "pointer" was really useful.
Only code <-> integer is a real lost, and also the typcast widget <-> unit/destructable/item (but it can be done with an hashtable)
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Ok, that would indeed be good to have the position in the string table of a string, for the ASCII library we would be able to use directly the integer array variable (i mean without maths).
Hopefully even if it's not perfect StringHash is enough in most of cases, anyway it's not like we have other ways.
 
Level 10
Joined
Jul 12, 2009
Messages
318
but anyway, it could be useful to
SOMEONE =P

I don't think so...considering it doesn't actually work, at least not when I tested it.

1. Leaks a timer
2. Example won't even work due to uninitialized integer crashing the thread
3. Function itself won't even work due to no TriggerSleepAction meaning the loop will just run until the condition is satisfied, which will never happen since no time is passing during the loop, so it'll just terminate the thread due to an infinite loop
3b. Even if I'm wrong about the reason, I tried your function and no actions listed after set i = Wait(0.25) ran, so no matter what it for sure doesn't work
4. If you added TSA then it won't work for low values meaning this has no advantage over PolledWait

I was hoping there was some kind of magic with setting a local to a function's value rather than doing call Function, but, not as far as I can tell. Did you even test this? If it worked for you, can you upload a test map?
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
The only way to use a timer as friendly as TSA is to build a preprocessor which will split the code in as many functions as needed and also convert locals variables in globals. (and use a timer recycling or whatever)
It wouldn't be for speedfreaks but that would still be cool.
 
[...]and also convert locals variables in globals[...]

indexed globals of course
but someone made something like that with macros already (maybe you can find it with forum search)
edit:
http://www.wc3c.net/showthread.php?t=101988
even found that with hive forum search...weird
edit2:
and this is the one which was in my mind
http://www.hiveworkshop.com/forums/graveyard-418/vjass-sleepaction-new-wait-178185/
not perfect though (if it was everybody would use it and you would know about it :p)

and to contribute something:
rotate a vector by the angle of another vector
A will be rotated by the angle between x-axis and B
a is the length of A
you can remove everything with a if you normalize A
this is an image of what the first function does
returns the coordinates of C
102269d1306608579-formula-request-3d-vector-rotation-rotation.png

JASS:
function subtractVectorAngleX takes real ax, real ay, real bx, real by, real a returns real
    return ax/a*bx + ay/a*by
endfunction

function subtractVectorAngleY takes real ax, real ay, real bx, real by, real a returns real
    return ay/a*bx - ax/a*by
endfunction

function addVectorAngleX takes real ax, real ay, real bx, real by, real a returns real
    return ax/a*bx - ay/a*by
endfunction

function addVectorAngleY takes real ax, real ay, real bx, real by, real a returns real
    return ay/a*bx + ax/a*by
endfunction
probably quite simple but I had a need for it
I also requested a 3D version and maybe someone is kind enough to answer my biddings :grin:
you can find the derivation there
http://www.hiveworkshop.com/forums/requests-341/formula-request-3d-vector-rotation-196220/
 
JASS:
MAX_COORD = 32556
MIN_COORD = -32556
MAX_RANGE = 92083

Yeah! :D
Those are useful :D

-> In library form:

JASS:
library Constants
    globals
        real MAX_COORD = 32556.
        real MIN_COORD = -MAX_COORD
        real MAX_RANGE = 92083.
    endglobals
endlibrary

This may be useful too:

An array lookup is much faster than a function call:
JASS:
library Players
    globals
        player array PLAYER
    endglobals
    private module Init
        private static method onInit takes nothing returns nothing
            local integer i = 0
            loop
                exitwhen i > 15
                set PLAYER[i] = Player(i)
                set i = i + 1
            endloop
        endmethod
    endmodule
    private struct Inits
        implement Init
    endstruct
endlibrary
 
Here's a small "Clipboard" library :p
JASS:
library Clipboard
    private module Init
        private static method onInit takes nothing returns nothing
            set Clipboard.i = 0
            set Clipboard.s = ""
            set Clipboard.b = false
            set Clipboard.r = 0.0
        endmethod
    endmodule
    struct Clipboard extends array
        static integer i
        static string s
        static boolean b
        static real r
        
        static method copyI takes integer d returns nothing
            set thistype.i = d
        endmethod
        static method pasteI takes nothing returns integer
            return thistype.i
        endmethod
        
        static method copyS takes string d returns nothing
            set thistype.s = d
        endmethod
        static method pasteS takes nothing returns string
            return thistype.s
        endmethod
        
        static method copyB takes boolean d returns nothing
            set thistype.b = d
        endmethod
        static method pasteB takes nothing returns boolean
            return thistype.b
        endmethod
        
        static method copyR takes real d returns nothing
            set thistype.r = d
        endmethod
        static method pasteR takes nothing returns real
            return thistype.r
        endmethod
        
        implement Init
    endstruct
endlibrary

It's similar to Copy/Paste, but it only works for primitive values (For simplicity)
 
Here's a small math oriented snippet:

JASS:
library Powers
    function isPowerX takes real i, integer j returns boolean
        loop
            exitwhen i<j
            set i=i/j
        endloop
        return i==1.0
    endfunction
    
    // wrappers
    function isSquare takes real i returns boolean
        return isPowerX(i,2)
    endfunction
    
    function isCube takes real i returns boolean
        return isPowerX(i,3)
    endfunction
endlibrary
 
I think that's a fine example of why evaluating submissions should be illegal for me in the mornings -_-
I knew it :ogre_hurrhurr:

@ Bribe:
At least you were referring to something that actually makes sense :p
JASS:
function isDivisible takes integer i, integer j returns boolean
    local integer m=i-(i/j)*j
    if m<0 then
        return m+j==0
    endif
    return m==0
endfunction
 
Level 17
Joined
Jun 17, 2007
Messages
1,433
JASS:
library SphericalProjection /* v1.0.0.1
*************************************************************************************
*
*   */uses/*
*   
*       */ AutoFly /*       hiveworkshop.com/forums/submissions-414/autofly-unitindexer-version-195563/
*
************************************************************************************
*
*   function SphericalProjection takes real x, real y, real z, real facing, verticalFacing, unit whichUnit, real distance, real theta, real phi returns nothing
*       -   x,y,z,facing,verticalFacing     source position. Vertical facing is z facing of unit, normally 0.
*       -   whichUnit                       unit to project
*       -   distance                        distance from position
*       -   theta                           x,y angle, 0 radians would be directly in front
*       -   phi                             z angle, 0 radians would be flat, pi/2 directly above, 
*       -                                   -pi/2 directly below
*
************************************************************************************/
function SphericalProjection takes real x, real y, real z, real f, real vf, unit u, real d, real t, real p returns nothing
    set t=t+f
    set f=d*Sin(p+vf)
    call SetUnitX(u,Cos(t)*f)
    call SetUnitY(u,Sin(t)*f)
    call SetUnitFlyHeight(u,d*Cos(p+vf),10000)
endfunction
endlibrary
If I remember correctly, SetUnitFlyHeight(u,d*Cos(p+vf),0) is equivalent to call SetUnitFlyHeight(u,d*Cos(p+vf),<some arbitrarily high number>)
 
Top