• πŸ† 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[JASS] Would this be better optimized as a struct?

Status
Not open for further replies.
I have been working on a system for TacoBell, but at the same time the system is using simple Jass (I encapsulated it with a scope just to contain the variables) and I would like to optimize it as much as possible. Here is the overall process:

1. Slide system detects the lowest point in each units' proximities...
2. If slope is greater than 60 degrees, cause move the unit towards it.

Since I don't know much about structs, really I barely understand the global concept of them (yes I've read through all the tutorials but I don't see why they need to be created/declared as a type... like how does the game even know to interpret all these generated variables?), I think a good place to start learning is from editing my own work. Can you take a look at this and see if it even needs to be contained in a struct?

JASS:
//β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
scope Locator initializer Init
//β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
    globals
        private constant group The_Group = CreateGroup()
        private constant real SR3 = SquareRoot(3.)
        private constant location loc = Location(0.,0.)
        private real array cos
        private real array sin
    endglobals
//β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
    private function Found takes unit u,integer i,real SrcX,real SrcY,real SrcZ returns boolean
        local real To_X = SrcX + cos[i]
        local real To_Y = SrcY + sin[i]
        local real To_Z = GetLocationZ(loc)
        loop
            exitwhen (i == 0)
            set i = i - 1
            call MoveLocation(loc,SrcX + cos[i],SrcY + sin[i])
            if (GetLocationZ(loc) < To_Z) then
                set To_X = SrcX + cos[i]
                set To_Y = SrcY + sin[i]
                set To_Z = GetLocationZ(loc)
            endif
        endloop
        if (SrcZ - To_Z >= SR3) then
            call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl",SrcX,SrcY))
            call SetUnitX(u,To_X)
            call SetUnitY(u,To_Y)
        endif
        return true
    endfunction
//β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
    private function DoEval takes unit u returns nothing
        local integer i = 23
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local real z
        call MoveLocation(loc,x,y)
        set z = GetLocationZ(loc)
        loop
            call MoveLocation(loc,x + cos[i],y + sin[i])
            if (GetLocationZ(loc) < z) then
                exitwhen (Found(u,i,x,y,z))
            endif
            exitwhen (i == 0)
            set i = i - 1
        endloop
    endfunction
//β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
    private function Pick takes nothing returns nothing
        call DoEval(GetEnumUnit())
    endfunction
//β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
    private function Slide takes nothing returns nothing
        call ForGroup(The_Group,function Pick)
    endfunction
//β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
    private function Init takes nothing returns nothing
        local integer i = 0
        local trigger t = CreateTrigger()
        loop
            set cos[i] = 3.*Cos(15*(i+1)*bj_DEGTORAD)
            set sin[i] = 3.*Sin(15*(i+1)*bj_DEGTORAD)
            set i = i + 1
            exitwhen (i > 23)
        endloop
        call TriggerAddAction(t,function Slide)
        call TriggerRegisterTimerEvent(t,0.03,true)
        call GroupEnumUnitsInRect(The_Group,bj_mapInitialPlayableArea,null)
    endfunction
//β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
endscope
//β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”
 
Last edited:
Level 12
Joined
Apr 15, 2008
Messages
1,063
Well structs are like "containers" for multiple variables. The game doesn't need to recognize them, as they are translated to standart types. Each instance of the struct gets an integer ID, and the variables of that struct are saved in an global array, under that ID.
Since structs gets translated back to standart functions, converting to struct can't really be used to optimize anything.
In this case, you use 5 constants, so you really don't need to use a struct, since you don't have a single variable there :grin:

EDIT: Found IMHO 3 bugs.
1) you move Location twice, once in DoEval() and once in Found(), to same coordinates
2) it won't pick the lowest point, but the first point with slope>60 deg
3) the slope test is wrong, it considers distance as SrcX-To_X, which is wrong. a) you needed to use also Y cordinate ( SquareRoot( dx*dx+dy*dy ) ). Where dx = SrcX-ToX, dy = SrcY-ToY. Also, since dx=sin a and dy=cos a, we know that sin^2+cos^2=1, therefore the distance is always 1. The correct condition would be (SrcZ - To_Z) >= SR3
 
Actually the function "Found" creates a nearly-identical copy of the first loop, but this time it incorporates three new local variables (to x, to y, to z) mostly so that I can declare those locals with initial values and not declare them as empty values in the "DoEval" function.

I slightly change the loop in the "Found" function so that, in case the first loop was done, the second loop would just exit right away. I don't see how it would only evaluate the first-lowest point when the loop doesn't stop until it cycles through the full list of 24 array choices of cos and sin, and each time it finds a new lowest-point the variables are set to remember those points.

I never MoveLocation to the same coordinates in an iteration of this process. I think what you see is the first entry in the second loop follows the same equation as the first loop - but I change the "i" right before then so it is not a redundant feature.

The only redundant feature involving the location is GetLocationZ which I use twice on the same point only if a lower point was found. I could set it to a variable so that this doesn't happen, but that puts stress on the machine during the more common parts of the game when he's on flat surfaces so I'd rather be redundant in rare cases than be extra effecient during common cases (I feel that is, overall, the most efficient way to do this).

For finding that math fail, thank you =)
It's been 8 or 9 years since I studied geometry in grade school, so I was just copying the equation he gave. It looked strange to me that X was being used and not Y, and that you needed to find the absolute value of it. Seeing it from your angle makes a lot more sense now =)
 
Status
Not open for further replies.
Top