• 🏆 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!

Problem with lags in my map

Status
Not open for further replies.
Level 15
Joined
Dec 6, 2008
Messages
345
Hi.I need help with my problem.
I working to one map.In the map are spell SHot arrow.Problem is in triggers.
All functions working good,but after 10 or 20 minutes of shoting,computer begins lagging.More shoots = more lagging.
In triggers is set function: If player cast a spell,then CREATE ARROW to his position.After,if arrow colision with unit or if distance of arrow will be greater than 1500 = Remove Arrow from the game.
I don't know why is that lagging after few shoting.Can you help me with this problem?
People like this map,but i don't know how to fix it :cry:
I need fix that lags,somethink like "remove location udg_arrow" or somethink.And please i need this in GUI.
 
Level 15
Joined
Dec 6, 2008
Messages
345
Lulz, this is GUI converted, why did you do that. Anyway, there are no memory leak cleanups here, not even one. See a tutorial on removing leaks.

PS: Removing array location = call RemoveLocation(udg_LOCATION[udg_INDEX])

And if i have the array in the loop action?Than that will be?

call RemoveLocation(udg_arrow_projektil[udg_IntegerA]) ?
 
Level 8
Joined
Aug 1, 2008
Messages
420
no. RemoveLocation is for Point variables. For the "arrow projektil" im guessing thats a unit? That shouldnt really cause lag, just remove the unit and set that variable to null
 
Level 8
Joined
Aug 1, 2008
Messages
420
  • Set arrow_projectil[1] = no unit
  • Set arrow_projectil[2] = no unit
etc.

Its in the "preset" at the top. It says No unit. Select that
 
Level 13
Joined
Mar 4, 2009
Messages
1,156
That doesn't work,because the udg_arrow is array variable,so,what now?

i dont believe locations can make lags (not so fast)

if you have array just type what the name of variable and type what is in this
:fp: [ ]

for example
[player number of owner of unit(attacking unit)]

if you want random numbers

set INTEGER random number between 1 and 3
do something with POINT[INTEGER]
call RemoveLocation(udg_POINT [INTEGER])
 
Level 7
Joined
Aug 29, 2007
Messages
336
It's not locations afaik. If I've understood this right now it's units(dummies) which, if that's the problem, could be solved by adding an expiration timer on the units.
 
Level 15
Joined
Dec 6, 2008
Messages
345
I've done test with unit removing and unit killing.I set 2 regions.In first region unit footman create and move to second region.After entered to region unit footman removed.I've done calculator to adding removed units.After 5 minutes calculator added 2800 removed units.There isn't any lag.Game going fast with no lags.
I really don't have idea for fixing 1 arrow lagg.

I tested my map.Exactly every 10 second player shot arrow,number of players in game is 12.so...every 10 second shots 12 players 12 arrows.With max score 20 is game played cca30 minutes.12x6 = 72 arrows per minute.72x30 = 2160 arrows.
Game very lagging.
So...2800 removed units in test 1 = no lag
and...2160 removed units in test 2 = big laggs...so...where is the Special bug?

I thing this is not Location bug.I've done: udg_arrow_projectil[IntegerA] = null
Did not change anything...

You can try and download my map here http://www.hiveworkshop.com/forums/maps-564/forest-archers-v1-2-a-134826/

PS: YOu think,if i change Remove unit and set Kill unit,will that works?
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
Well the trigger obviously leaks, which you are failing to grasp. As you have not posted the trigger I can not tell you exactly where the leaks are but by the sounds of them you are probably leaking 1000s of handles per cast.

Incase you are too lazy to do research about what a leak is, it is when data is left in RAM after it is no longer needed and thus clogs it up nearly permantly. For example a location which you create by lose reference of leaks as you can no longer remove it and it is stuck in the memory until the game ends. This slows down general game performance as it is harder to find a handle index to use and also the game uses more RAM. I advise reading a tutorial, as this really is knowledge that every non melee map maker should know.

To fix leaks, you have to remove all non needed data so that proper recycling can occur.
Strings will always leak and there is no fix for this. . .

assasinater, do not double post, there is an edit button.
Also I doubt anyone would want to steal your map or even play your map in its current condition, so do not be parrionoid as people are trying to help you. If nescescary export the system in question to a special map demonstrating its function and submit that. If someone fixes it you can then reimport the system with out any concern for your map.

Killing units which do decay will eventually end in the same result as removing them. Basically they remain as a corpse of a time difined by the gameplay constants before being removed. This is generally a minute or two.

For dummies and stuff it is advisable to remove them as soon as possiable as some spells can create large numbers of them which under certain conditions can cause lag.
 
Last edited:
Level 8
Joined
Aug 1, 2008
Messages
420
Exactly what the Dr said. (haha...)

I wont steal your map. Im only trying to help, and if you dont want help, fine by me, but i was offering to do something that will probably take you a few hours.
 
Level 15
Joined
Dec 6, 2008
Messages
345
So here is the Trigger(GUI)


  • Function1
    • Events
      • Timer - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 12, do (Actions)
        • Loop - action
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Condition
              • arrow_bolean[(Integer A)] equal to TRUE
            • than - action
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Condition
                  • arrow_distance[(Integer A)] Less than MaxDistance[(Integer A)]
                • Than - action
                  • Set arrow_distance[(Integer A)] = (arrow_distance[(Integer A)] + MaxSpeed[(Integer A)])
                  • Unit - Move arrow_projektil[(Integer A)] instantly to ((Position of arrow_projektil[(Integer A)]) offset by MaxSpeed[(Integer A)] towards (Facing of arrow_projektil[(Integer A)]) degrees)
                  • Set arrow_target[(Integer A)] = (Random unit from (Units within 55.00 of (Position of arrow_projektil[(Integer A)]) matching ((Matching unit) not equal to arrow_projektil[(Integer A)])))
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - conditions
                      • arrow_target[(Integer A)] not equal to no unit
                      • arrow_target[(Integer A)] not equal arrow_caster[(Integer A)]
                      • (arrow_target[(Integer A)] is dead) aqual to FALSE
                    • than - action
                      • sound - Play MetalLightSliceFlesh <gen> at 100.00% volume, attached to arrow_projektil[(Integer A)]
                      • Unit - Cause arrow_caster[(Integer A)] to damage arrow_target[(Integer A)], dealing (Random real number between 1.00 and 2.00) damage of attack type Chaos and damage type Normal*
                      • Special effect - Create a special effect attached to the overhead of arrow_target[(Integer A)] using Objects\Spawnmodels\Orc\Orcblood\OrdBloodWyvernRider.mdl
                      • Unit - Add a 0.01 second Normal expiration timer to arrow_projektil[(Integer A)]
                      • Set arrow_projektil[(Integer A)] = no unit
                      • Set knockback_target[(Integer A)] = arrow_target[(Integer A)]
                      • Set knockback_integer[(Integer A)] = 8.00
                      • Set knockback_bolean[(Integer A)] = TRUE
                      • Set arrow_bolean[(Integer A)] = FALSE
                      • Set arrow_distance[(Integer A)] = 0.00
                      • Animation - Change arrow_caster[(Integer A)]'s animation speed to 100.00% of its original speed
                    • Else- action
                • Else - action
                  • Unit - Add a 0.01 second Normal expiration timer to arrow_projektil[(Integer A)]
                  • Set arrow_projektil[(Integer A)] = no unit
                  • Set arrow_bolean[(Integer A)] = FALSE
                  • Set arrow_distance[(Integer A)] = 0.00
                  • Animation - Change arrow_caster[(Integer A)]'s animation speed to 100.00% of its original speed
            • Else - action

Same trigger in Jass:


JASS:
function Trig_Function1_Func001Func001Func001Func009002001003 takes nothing returns boolean
    return ( GetFilterUnit() != udg_arrow_projektil[GetForLoopIndexA()] )
endfunction

function Trig_Function1_Func001Func001Func001Func010C takes nothing returns boolean
    if ( not ( udg_arrow_target[GetForLoopIndexA()] != null ) ) then
        return false
    endif
    if ( not ( udg_arrow_target[GetForLoopIndexA()] != udg_arrow_caster[GetForLoopIndexA()] ) ) then
        return false
    endif
    if ( not ( IsUnitDeadBJ(udg_arrow_target[GetForLoopIndexA()]) == false ) ) then
        return false
    endif
    return true
endfunction

function Trig_Function1_Func001Func001Func001C takes nothing returns boolean
    if ( not ( udg_arrow_distance[GetForLoopIndexA()] < udg_MaxDistance[GetForLoopIndexA()] ) ) then
        return false
    endif
    return true
endfunction

function Trig_Function1_Func001Func001C takes nothing returns boolean
    if ( not ( udg_arrow_bolean[GetForLoopIndexA()] == true ) ) then
        return false
    endif
    return true
endfunction

function Trig_Function1_Actions takes nothing returns nothing
    set bj_forLoopAIndex = 1
    set bj_forLoopAIndexEnd = 12
    loop
        exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
        if ( Trig_Function1_Func001Func001C() ) then
            if ( Trig_Function1_Func001Func001Func001C() ) then
                set udg_arrow_distance[GetForLoopIndexA()] = ( udg_arrow_distance[GetForLoopIndexA()] + udg_MaxSpeed[GetForLoopIndexA()] )
                call SetUnitPositionLoc( udg_arrow_projektil[GetForLoopIndexA()], PolarProjectionBJ(GetUnitLoc(udg_arrow_projektil[GetForLoopIndexA()]), udg_MaxSpeed[GetForLoopIndexA()], GetUnitFacing(udg_arrow_projektil[GetForLoopIndexA()])) )
                set udg_arrow_target[GetForLoopIndexA()] = GroupPickRandomUnit(GetUnitsInRangeOfLocMatching(55.00, GetUnitLoc(udg_arrow_projektil[GetForLoopIndexA()]), Condition(function Trig_Function1_Func001Func001Func001Func009002001003)))
                if ( Trig_Function1_Func001Func001Func001Func010C() ) then
                    call PlaySoundOnUnitBJ( gg_snd_MetalLightSliceFlesh, 100, udg_arrow_projektil[GetForLoopIndexA()] )
                    call UnitDamageTargetBJ( udg_arrow_caster[GetForLoopIndexA()], udg_arrow_target[GetForLoopIndexA()], GetRandomReal(1.00, 2.00), ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL )
                    call AddSpecialEffectTargetUnitBJ( "overhead", udg_arrow_target[GetForLoopIndexA()], "Objects\\Spawnmodels\\Orc\\Orcblood\\OrdBloodWyvernRider.mdl" )
                    call UnitApplyTimedLifeBJ( 0.01, 'BTLF', udg_arrow_projektil[GetForLoopIndexA()] )
                    set udg_arrow_projektil[GetForLoopIndexA()] = null
                    set udg_knockback_target[GetForLoopIndexA()] = udg_arrow_target[GetForLoopIndexA()]
                    set udg_knockback_integer[GetForLoopIndexA()] = 8.00
                    set udg_knockback_bolean[GetForLoopIndexA()] = true
                    set udg_arrow_bolean[GetForLoopIndexA()] = false
                    set udg_arrow_distance[GetForLoopIndexA()] = 0.00
                    call SetUnitTimeScalePercent( udg_arrow_caster[GetForLoopIndexA()], 100.00 )
                else
                endif
            else
                call UnitApplyTimedLifeBJ( 0.01, 'BTLF', udg_arrow_projektil[GetForLoopIndexA()] )
                set udg_arrow_projektil[GetForLoopIndexA()] = null
                set udg_arrow_bolean[GetForLoopIndexA()] = false
                set udg_arrow_distance[GetForLoopIndexA()] = 0.00
                call SetUnitTimeScalePercent( udg_arrow_caster[GetForLoopIndexA()], 100.00 )
            endif
        else
        endif
        set bj_forLoopAIndex = bj_forLoopAIndex + 1
    endloop
endfunction

//===========================================================================
function InitTrig_Function1 takes nothing returns nothing
    set gg_trg_Function1 = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Function1, 0.01 )
    call TriggerAddAction( gg_trg_Function1, function Trig_Function1_Actions )
endfunction
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
Timer - Every 0.01 seconds of game time
Far too fast, WC3 only visually updates on average 60 times a second so anything more simply wastes system resources. I advise setting it to 0.02 or even 0.03 as both are visually about the same yet use only 1/2 or 1/3 of the resources per second.

Unit - Move arrow_projektil[(Integer A)] instantly to ((Position of arrow_projektil[(Integer A)]) offset by MaxSpeed[(Integer A)] towards (Facing of arrow_projektil[(Integer A)]) degrees)
This leaks 2 locations by itself. Comming to atleast 200 locations leaks in this line alone per second when used for 1 loop. It is well capable of leaking up to 2400 locations per second in this very line alone. No wonder it lags with that many leaks...

Set arrow_target[(Integer A)] = (Random unit from (Units within 55.00 of (Position of arrow_projektil[(Integer A)]) matching ((Matching unit) not equal to arrow_projektil[(Integer A)])))
This leaks a group. This comes to between 100 and 1200 group leaks per second. How could you be so careless.

Special effect - Create a special effect attached to the overhead of arrow_target[(Integer A)] using Objects\Spawnmodels\Orc\Orcblood\OrdBloodWyvernRider.mdl
This leaks a special effect as you never destory it at a later time, which helps account for graphic lag. That comes to about 100-1200 special effect leaks per second.

Ofcourse this would scale inversly with the update interval so 0.02 seconds would half the number of leaks per second but that is no fix for any leaks in the first place. Honestly I am suprized you are wondering why WC3 lags with such obvious leakage but anyway.

Firstly lower the update interval to 0.02. Secondly remove all the above leaks. Finally enjoy your now leak free and lagless map.

Ofcourse a little bit of simple JASS is needed to do this but I am sure you are a capable person once you read a tutorial or two.

Also this should get moved to triggers and scripts.
 
Level 15
Joined
Dec 6, 2008
Messages
345
Thx for help,but i have question,how it change the bugs like:

Unit - Move arrow_projektil[(Integer A)] instantly to ((Position of arrow_projektil[(Integer A)]) offset by MaxSpeed[(Integer A)] towards (Facing of arrow_projektil[(Integer A)]) degrees)


Set arrow_target[(Integer A)] = (Random unit from (Units within 55.00 of (Position of arrow_projektil[(Integer A)]) matching ((Matching unit) not equal to arrow_projektil[(Integer A)])))

Can you help?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
Read a leak tutorial Like I said.
Basically you store the locations / groups in variables then remove / destroy them via natives. I advise the use of local variables for this although globals work fine as well and need not be nulled in this case.

Thuse the peudocode for that part of your code looks like this.

Creation of handle (location/group)
Use of handle
Destruction of Handle (via DestroyGroup() or RemoveLocation() natives)
 
Status
Not open for further replies.
Top