• 🏆 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] Does WorldEdit have a Limit on loops?

Status
Not open for further replies.
Level 7
Joined
Jun 16, 2008
Messages
253
As in loop within loops.

I have probably eight loops all inside each other, I know that's really probably a silly amount but I was combining systems to make it more efficient and the like.

When I run the map (1.21 / newgen) it runs right through to the most inside inside loop(checked by calling one-off spec effects in each loop), but only comes out of about six of them, apparently. That probably didn't make much sense.

Anyway, Warcraft III newgen tells me I'm breaking the oplimit, or that it failed to 'get_' whatever I was retrieving.

When I get rid of the most inside loop though, it seems to be fine.

Is this because of some inbuilt memory protector deal? Could appreciate if someone could tell me, so that I know if I have to rework the system.

Cheers,

Al
 
Level 12
Joined
Dec 10, 2008
Messages
850
huh... What do these loops do, more specificly, do that init things, do they create/destroy thing? The trigger would be helpful, even if you just cut out the loops and pasted them here. It might be a protection thing with Warcaft.
\
 
Level 7
Joined
Jun 16, 2008
Messages
253
:)

I can give you the trigger, but just so you know, it might be... confusing. I'm building new systems. :) It's calculating stats of component objects and the abstract object that they are a component of.

The part I'm talking about is under Stage 1, but I imagine Stage 2 will be the same because it's very similiar.

attribute is a struct.

Please have a look and see what you can see. :)

JASS:
function Trig_Find_Velocity_Actions takes nothing returns nothing
    local unit u = null
    local integer ui = 0
    local real uf = 0
    local real ux = 0
    local real uy = 0
    local real dist =  0
    local location loc = null
    local real z = 0
    local real ux2 = 0
    local real uy2 = 0
    local location locb = null
    local real zb = 0
    local real ds = 0
    local real vp = 0
    local real ang
    local attribute a = 0
    local attribute b = 0
    local rect wb = GetWorldBounds()
    local integer i = 0
    local integer i2 = 0
    local integer i3 = 0
    local integer i4 = 0
    local real totalmass = 0
    local real uz = 0
    local real ufh = 0
    //Reader Part============================================================
    local integer position1 = 0
    local integer position2 = 0
    local integer length = 0
    local boolean bool = false
    //========================================
    
    call GroupEnumUnitsInRect(udg_Group, wb, null)
  
    
//Stage 1: Resetting the Stats//==================================================================================  
    
    set i = udg_maxfundlevel
loop //There are some slight differences here from Stage 2. One is that the string we are looking for (overunit) is in the abilities slot, not the pro_symp slot. The other is that we are resetting elements as well as mass.
exitwhen i < 0 //This goes in reverse direction of Stage 2, because we are looking for Overunits, not components.
loop
exitwhen i2 > udg_assignID
    set a.mass = 0 //reset mass
    set length = StringLength(a.abilities)
if a.fundamental_level == i then
   
    //Check to see if it is overunit and stuff.
    loop
    exitwhen i3 > udg_assignID
    loop
        exitwhen position1 > length or bool == true
    loop
        exitwhen position2 > length or bool == true
        if SubString(a.abilities, position1, position2) == "overunit" and SubString(a.abilities, position2, position2 + 1) == ";" then
        set bool = true //It found the "overunit" string it wanted, so after the below loop, it's finished with this unit and can exit the loops.
        set b = a.sympathetic_object[i3]
        set i4 = 0
            //Now I'm resetting every element and compound in overunit//=====================
            loop
            exitwhen i4 > 100 
            set b.element[i4] = 0  //This is resetting the overunit's elements and compounds, because they will be recalculated in Stage 2. :)
            set b.compound[i4] = 0 //This could be interesting, if say two pure element objects were components, wouldn't that make them a compound? But that's future thinking.
    
    if udg_tempbool4 == true then
    call DisplayTextToForce( GetPlayersAll(), "S0:STARTED!" + I2S(udg_maxfundlevel))
        call AddSpecialEffectLocBJ( GetUnitLoc(gg_unit_ERoc_0031), "Doodads\\Cinematic\\Lightningbolt\\Lightningbolt.mdl" )  
    set udg_tempbool4 = false  
    else
    endif
  
            set i4 = i4 + 1
            endloop
            set i4 = 0
            //=======================================================================================
        else
        endif
        set position2 = position2 + 1 //If bool is true then this is superfluous, but it gets reset after loop anyway. :)
    endloop
            if udg_tempbool1 == true then
            call DisplayTextToForce( GetPlayersAll(), "S1:Reset Elements and Compounds!")
            call AddSpecialEffectLocBJ( GetUnitLoc(gg_unit_ERoc_0034), "Doodads\\Cinematic\\Lightningbolt\\Lightningbolt.mdl" )
            set udg_tempbool1 = false
            else
            endif
        set position1 = position1 + 1
        set position2 = position1
    endloop 
                if udg_tempbool2 == true then
                call AddSpecialEffectLocBJ( GetUnitLoc(gg_unit_ERoc_0030), "Doodads\\Cinematic\\Lightningbolt\\Lightningbolt.mdl" )          
                set udg_tempbool2 = false
                else
                endif
                
        set position1 = 0    
        set position2 = 0
    set bool = false
    set i3 = i3 + 1
    endloop

                if udg_tempbool3 == true then
                call AddSpecialEffectLocBJ( GetUnitLoc(gg_unit_UBoo_0019), "Doodads\\Cinematic\\Lightningbolt\\Lightningbolt.mdl" )          
                set udg_tempbool3 = false
                else
                endif

    set i3 = 0
else
endif
    set i2 = i2 + 1
    set a = i2
endloop
                set i2 = 0
    set i = i - 1 //It's supposed to be negative. :) It's counting down from maxfundlevel.
endloop


    set i = 0
    set i2 = 0
    set i3 = 0
    set i4 = 0
    set bool = false
    set position1 = 0
    set position2 = 0
    set length = 0

    
//Stage 2: Matter and Energy//====================================================================================

loop
exitwhen i > udg_maxfundlevel //Checking every unit, fundament level by level.
loop
exitwhen i2 > udg_assignID
    set a = i2
    //set a.mass = 0 //This should be taken care of by Stage 1. Resetting stats. :)
if a.fundamental_level == i then
    loop
    exitwhen i3 > 100 //Max number of elements. Don't need to count compounds, they are just another version of overunit.
    set a.mass = a.mass + a.element[i3] //Calculate mass.
    set i3 = i3 + 1
    endloop
    set i3 = 0    
    //Check to see if it is a component and stuff.
    loop
    exitwhen i3 > udg_assignID
    set length = StringLength(a.pro_sympathetic_object[i3])
    loop
        exitwhen position1 > length or bool == true
    loop
        exitwhen position2 > length or bool == true
        if SubString(a.pro_sympathetic_object[i3], position1, position2) == "component_of" and SubString(a.pro_sympathetic_object[i3], position2, position2 + 1) == ";" then
        set bool = true //It found the "component_of" string it wanted, so after the below loop, it's finished with this unit and can exit the loops.
        set b = a.sympathetic_object[i3]
        set b.fundamental_level = a.fundamental_level + 1 //Fundamental level upgrader!!! Can probably delete the one in structs.
        set i4 = 0
            //Now I'm adding every element from component object to overunit.//=====================
            loop
            exitwhen i4 > 100 
            set b.element[i4] = b.element[i4] + a.element[i4]  //Keep checking this. Make sure that the overunit gets set to 0 properly before this whole thing, and that this function isn't repeatedly just overwriting it. Must add-on properly.
            set b.compound[i4] = b.compound[i4] + a.compound[i4]

            set i4 = i4 + 1
            endloop
            set i4 = 0
            //=======================================================================================
        else
        endif
        set position2 = position2 + 1 //If bool is true then this is superfluous, but it gets reset after loop anyway. :)
    endloop
        set position1 = position1 + 1     
        set position2 = position1
    endloop 
        set position1 = 0    
        set position2 = 0
    set bool = false
    set i3 = i3 + 1
    endloop
    set i3 = 0
        //Remove massless/non-existing units//=================================
    if a.mass == 0 then //I just put it as == instead of <= just to see if anything interesting happens with negatives. :) 'Nature' abhors a vacuum, so I wanna see what it does about it.
    //Here is where the object will de-associate with every other object before dying. Should Remove non-existent units happen before or after I add it's attributes and the like. Logic dictates before, but the script itself happens to favour after.
    call RemoveUnit(udg_unit[i2]) //This shouldn't exist in future installments, units are pretty much just special effects in my system. Only destroy struct should work.
    call a.destroy() //Will that work? Looks like it... the map saved.
    else
    endif
    //=====================================================================
else
endif
    set i2 = i2 + 1
endloop
    set i2 = 0
    set i = i + 1
endloop

    set i = 0
    set i2 = 0
    set i3 = 0
    set i4 = 0
    set bool = false
    set position1 = 0
    set position2 = 0
    set length = 0  

//Stage 3: Velocity and Slope//=========================================================================

loop
    set u = FirstOfGroup(udg_Group)
    set ui = GetUnitUserData(u)
    set a = ui
exitwhen u == null
    //local real ad = Atan2(((z) - (zb)), vp) * bj_RADTODEG //Atan2BJ(((z) - (zc)), vp)
       
    set uf = GetUnitFacing(u)
    set ux = GetUnitX(u)
    set uy = GetUnitY(u)
    set dist =  SquareRoot((ux - udg_LastPositionX[ui]) * (ux - udg_LastPositionX[ui]) + (uy - udg_LastPositionY[ui]) * (uy - udg_LastPositionY[ui]))//DistanceBetweenPoints(udg_LastPositionX[i], l)
    set loc = Location(ux,uy) 
    set z = GetLocationZ(loc)
    set ux2 = (ux + dist * Cos(uf * bj_DEGTORAD))
    set uy2 = (uy + dist * Sin(uf * bj_DEGTORAD))
    set locb = Location(ux2,uy2)
    set zb = GetLocationZ(locb)
    set ds = GetUnitDefaultMoveSpeed(u)
    set vp = SquareRoot((ux2 - ux) * (ux2 - ux) + (uy2 - uy) * (uy2 - uy)) //DistanceBetweenPoints(loc, locb)
    set ang = Atan2(((zb) - (z)), vp) * bj_RADTODEG //Atan2BJ(((zc) - (z)), vp)
    set uz = GetLocationZ(loc)
    set ufh = GetUnitFlyHeight(u)
    set a.x = ux
    set a.y = uy
    set a.z = uz + ufh
    
if ang > 70 then //This factor of angle that the unit can traverse will later be calculated with things like grip and traction + technique. Rock climbing for example.
    call SetUnitMoveSpeed(u, 0)
    else
    call SetUnitMoveSpeed(u, ds / 90 * (90 - ang))
endif
    set udg_Velocity[ui] = dist * 10
    set udg_LastPositionX[ui] = ux
    set udg_LastPositionY[ui] = uy
    set a = 0
    call GroupRemoveUnit(udg_Group, u)
endloop

//Nulling the data.==================================================================================
    set u = null
    set ui = 0
    set uf = 0
    set dist = 0
    set ux = 0
    set uy = 0
    set loc = null 
    set z = 0
    set ux2 = 0
    set uy2 = 0
    set locb = null
    set zb = 0
    set ds = 0
    set vp = 0
    set ang = 0
    set a = 0
    set wb = null
    set i = 0
    set totalmass = 0
    set uz = 0
    set ufh = 0

endfunction

//===========================================================================
function InitTrig_Physics takes nothing returns nothing
    set gg_trg_Physics = CreateTrigger(  )
    call DisableTrigger( gg_trg_Physics )
    call TriggerRegisterTimerEvent( gg_trg_Physics, 0.1, true )
    call TriggerAddAction( gg_trg_Physics, function Trig_Find_Velocity_Actions )
endfunction



Hopefully you could make some sense out of that, I'm still learning jass.

Cheers,

Al
 
Level 7
Joined
Jun 16, 2008
Messages
253
Hang on. It may not be a loop thing. I'm not sure yet, but I'm still working with it. :D

I'd disregard this thread for now, or delete it, and I'll just repost if I figure out where the problem lies, and can't fix it. :)

Cheers,

Al
 
The problem IS with the loops. If you try to execute too much code at once it "breaks the op limit" and the code crashes. All you need to do is run some of the code in several different threads, by putting them in functions and using either ExecuteFunc or the vJass call <functionName>.execute(). Keep in mind the vJass version can use parameters, so you can pass all the parameters you need.
 
Level 7
Joined
Jun 16, 2008
Messages
253
YOU ARE A GOLDEN JASS GOD! WOOT!

I was trying to avoid the .executes, but can't help that I guess.

Thank you very much, problem solved. :)
 
Status
Not open for further replies.
Top