• 🏆 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] Heavy lagg-but all leaks removed

Status
Not open for further replies.
Level 9
Joined
Aug 21, 2008
Messages
533
After finishing the first part of my spell i tried the second part. altought it works it profuce heavy lagg and isnt really working...

JASS:
function DeadFilter takes nothing returns boolean
return GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) < 0.5
endfunction

function GetClosestUnit takes unit u2, boolexpr e returns unit
   local real md = 200
    local group g = CreateGroup()
    local unit u
    local real d
    local location l = GetUnitLoc(u2)
    local location l2
    local unit u3
    call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, e)
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null
        if (GetOwningPlayer(u)==GetOwningPlayer(u)) then
            else
            set l2 = GetUnitLoc(u2)
            set d= DistanceBetweenPoints(l,l2)
            call RemoveLocation(l)
            call RemoveLocation(l2)
            if d > 0 then
               if d < md then
               set md = d
               set u = u3
               endif
            endif
        endif    
   endloop
   call DestroyGroup(g)
   call DestroyBoolExpr(e)
   set g = null
   set u = null
   set u2 = null
   set l = null
   set l2 = null
return u3
endfunction

function Fly takes nothing returns nothing
 local real r
 local real an
 local real sp
 local unit u = GetEnumUnit()
 local real da = LoadReal( udg_hashTable, GetHandleId(u), StringHash("damage"))
 local unit u2
 local location l
 local location l2
 local boolexpr f = Condition(function DeadFilter)
 set r = LoadRealBJ(StringHash("time"), GetHandleId(u), udg_hashTable )
 if (r>0.00) then
  set r = r-0.03
  call SaveRealBJ(r,StringHash("time"), GetHandleId(u), udg_hashTable )
  set an = LoadRealBJ(StringHash("missleangle"), GetHandleId(u), udg_hashTable )
  set sp = LoadRealBJ(StringHash("misslespeed"), StringHash(GetUnitName(u)), udg_hashTable)/33
  set l = GetUnitLoc(u)
  set l = PolarProjectionBJ(l, sp, an)
  call SetUnitPositionLoc(u,l)
  set u2 = GetClosestUnit(u,f)
  call RemoveLocation(l)    
  call RemoveLocation(l2)
  set l = GetUnitLoc(u)
  set l2 = GetUnitLoc(u2)
  if (DistanceBetweenPoints(l,l2)<50) then
    call GroupRemoveUnit(udg_misslegroup,u)
    call UnitDamageTargetBJ( u, u2, da*100, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL )
    call KillUnit(u)
  endif
  call RemoveLocation(l)    
  call RemoveLocation(l2)
 else
  call GroupRemoveUnit(udg_misslegroup,u)
  call KillUnit(u)
 endif
 set u = null
 set l = null
 set l2 = null
 set u2=null
 endfunction

function Trig_Fly_Actions takes nothing returns nothing
    call ForGroup(udg_misslegroup, function Fly )
endfunction
//===========================================================================
function InitTrig_Fly takes nothing returns nothing
    set gg_trg_Fly = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Fly, 0.03 )
    call TriggerAddAction( gg_trg_Fly, function Trig_Fly_Actions )
endfunction
 
Level 8
Joined
Aug 4, 2006
Messages
357
Lol, do you realize what you're doing? The coding in general could use a lot of improvement, but what's causing your lag is your horrible GetClosestUnit function (no offense). Every .03 seconds, you loop over all the units in udg_missilegroup, and Enum all the units in the ENTIRE MAP, for each unit. Then you loop over all those units. So if you have 100 units on your map, and 2 missles, you will be looping 200 times every .03 seconds AKA 6667 times a second.

I would suggest using this system in place of your GetClosestUnit function: http://www.hiveworkshop.com/forums/jass-functions-413/getclosestunit-s-59254/. I would also suggest learning how to use coordinates instead of locations, or at least making global locations and moving them instead of constantly creating/removing/destroying your local locations. You should also stop using most BJ functions because they pretty much suck. Get JassNewGen so you can see what functions to use instead of the BJs.
 
Level 8
Joined
Aug 4, 2006
Messages
357
I still think the problem is the GetClosestUnit function. I'm not sure how GroupEnumUnitsInRect works internally, but doing it over the entire map probably takes a lot of processing and is totally unnecessary for your function. In your Fly function, just try replacing set u2 = GetClosestUnit(u,f) with set u2 = somePrePlacedUnit (i.e. gg_unit_hpea_0000). Then you will know if GetClosestUnit is causing the lag.
 
Level 6
Joined
Mar 20, 2008
Messages
208
JASS:
        if (GetOwningPlayer(u)==GetOwningPlayer(u)) then

Might be one of your problems, that will always return true.

I suggest you comment your code or atleast tell us basic directions because after reading that line it didn't seem worth the effort to pick apart.
 
JASS:
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null
        if (GetOwningPlayer(u)==GetOwningPlayer(u)) then
            else
            set l2 = GetUnitLoc(u2)
            set d= DistanceBetweenPoints(l,l2)
            call RemoveLocation(l)
            call RemoveLocation(l2)
            if d > 0 then
               if d < md then
               set md = d
               set u = u3
               endif
            endif
        endif
        //////////////////////////////////////////////////////////
        call GroupRemoveUnit(g, u) // NEED THIS LINE!!!!!///
        //////////////////////////////////////////////////////////
   endloop
Your loop is currently infinite...
 
Level 8
Joined
Aug 4, 2006
Messages
357
JASS:
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null
        if (GetOwningPlayer(u)==GetOwningPlayer(u)) then
            else
            set l2 = GetUnitLoc(u2)
            set d= DistanceBetweenPoints(l,l2)
            call RemoveLocation(l)
            call RemoveLocation(l2)
            if d > 0 then
               if d < md then
               set md = d
               set u = u3
               endif
            endif
        endif
        //////////////////////////////////////////////////////////
        call GroupRemoveUnit(g, u) // NEED THIS LINE!!!!!///
        //////////////////////////////////////////////////////////
   endloop
Your loop is currently infinite...
Oh, how did I miss that... I guess I never do those kinds of group loops; I always use ForGroup or the GroupEnum filter.

In most cases in wc3, an infinite loop causes the game to crash. One of the few times that it doesn't is when the loop is explicitly written out between the words loop/endloop. In this case, wc3 automatically stops the thread after a certain amount of time (at which point wc3 realizes the loop has been going so long that it will probably never stop). This time is actually pretty small (something like .01 seconds), but since this script causes an infinite loop every .03 seconds, the infinite loop causes lag.

However, even if the OP adds that GroupRemoveUnit line, he may still experience lag due to how inefficient the function is. He should definitely replace that with a better one and learn from it.
 
Level 8
Joined
Aug 4, 2006
Messages
357
maskedpoptart, no, infinite
JASS:
loop
...
endloop
loops never cause the game to crash. They have an execution limit of 2^16, so they stop after 60-odd thousand loops. But yeah, it causes a lot of lag.

Ya that's what I meant. The infinite loops that actually crash games are the kind that involve triggers setting off themselves. I'm not sure about the execution limit; I think there is a time limit, not an execution limit, for each loop. I found that the more crap you put in a loop, the less it executes before wc3 stops the thread. Since the extra crap takes extra time, I came to the conclusion that loops are only allowed to run a certain length of time, even if they are not infinite, because wc3 cannot tell when a loop is infinite or finite.
 
Level 9
Joined
Nov 28, 2008
Messages
704
I could have sworn that a thread was only allowed to execute X "commands" like setting a variable or calling a function, NOT the amount of times it loops, or time.
 
Level 9
Joined
Nov 28, 2008
Messages
704
That is something I really don't know. I've had enough trouble with large loops (say 1000 iterations) and removing around a thousand special effects, and it stopping randomly and only deleting half. I would ASSUME it would count the things that the functions do, but I don't know.

Perhaps DSG could enlighten us? Or hell, why don't I just go test it?

Test results: 6387 or something loops with a smallish function.

3876 (or around there) loops with a larger function.

So yes, the size of functions matters, and time likely does not. However many iterations of a loop it can do, I have no idea. But it DOES count the size of the function, and how many commands are executed, so now I know. :D
 

Attachments

  • Thread Test.w3m
    11.7 KB · Views: 57
Level 8
Joined
Jul 9, 2006
Messages
41
I've edited your function.
JASS:
    loop
        exitwhen false
        set udg_TempInt=udg_TempInt+1
    endloop
Yields 33333.
JASS:
    loop
        exitwhen false
        set udg_TempInt=udg_TempInt+1
        if udg_TempInt==18745 then
        call DisplayTextToForce(GetPlayersAll(), "Reached recursion limit")
        call TriggerSleepAction(1.0)
        endif
    endloop
Yields 37495.
 
Status
Not open for further replies.
Top