- Joined
- Sep 26, 2012
- Messages
- 5
can i ask a Q. if you dont mind i want to know if the creation of a unit and i forgot to trigger it with an action "Remove (Bla bla) from game" will the unit cause a leak?
1. What if I create a group and keep "picking every unit" from the same group with out destroying it? Is this leaking?
2. If it doesnt, then what if I add or remove units by some conditions in that group? Does that create some how like a new leaky memory or?
Usually when Im kicked out of WC3 with errors like "out of memory" and such, it means the map leaked allot. What if the game kicks you out, with out even saying the error reason? Does that means the map leaked?
function GM_GodMode_Exit takes nothing returns nothing
call DisableTrigger(GetTriggeringTrigger())
call DisableTrigger(udg_t_godmode[1])
call DisableTrigger(udg_t_godmode[2])
call DisableTrigger(udg_t_godmode[3])
call DisableTrigger(udg_t_godmode[4])
call DisableTrigger(udg_t_godmode[5])
call DisableTrigger(udg_t_godmode[6])
call DisableTrigger(udg_t_godmode[7])
call DisableTrigger(udg_t_godmode[8])
call DisableTrigger(udg_t_godmode[9])
call DisableTrigger(udg_t_godmode[10])
call DisableTrigger(udg_t_godmode[11])
call DisableTrigger(udg_t_godmode[12])
call DisableTrigger(udg_t_godmode[13])
call DisableTrigger(udg_t_godmode[14])
call SetPlayerHandicap(udg_God,100.00*0.01)
call EnableTrigger(gg_trg_God_Mode)
call DisableTrigger(gg_trg_Restart)
call DisableTrigger(gg_trg_MM_Restart)
call DisplayTextToForce(bj_FORCE_ALL_PLAYERS,(udg_PlayerName[GetPlayerId(udg_God)+1]+" has disabled God Mode."))
endfunction
//===========================================================================
function InitTrig_God_Mode takes nothing returns nothing
local integer i=1
set gg_trg_God_Mode=CreateTrigger()
loop
exitwhen i>12
call TriggerRegisterPlayerChatEvent(gg_trg_God_Mode,Player(i),"-godmode",true)
set i=i+1
endloop
call TriggerAddCondition(gg_trg_God_Mode,Condition(function Trig_God_Mode_Conditions))
call TriggerAddAction(gg_trg_God_Mode,function Trig_God_Mode_Actions)
endfunction
function God_Mode_Commands takes nothing returns nothing
set udg_t_godmode[1]=CreateTrigger()
call TriggerRegisterPlayerChatEvent(udg_t_godmode[1],udg_God,"-control",true)
call TriggerAddAction(udg_t_godmode[1],function GM_Control)
set udg_t_godmode[2]=CreateTrigger()
call TriggerRegisterPlayerChatEvent(udg_t_godmode[2],udg_God,"-controloff",true)
call TriggerAddAction(udg_t_godmode[2],function GM_ControlOff)
set udg_t_godmode[3]=CreateTrigger()
call TriggerRegisterPlayerChatEvent(udg_t_godmode[3],udg_God,"-teamshare",false)
call TriggerAddAction(udg_t_godmode[3],function GM_TeamShare)
set udg_t_godmode[4]=CreateTrigger()
call TriggerRegisterPlayerChatEvent(udg_t_godmode[4],udg_God,"-teamremove",false)
call TriggerAddAction(udg_t_godmode[4],function GM_TeamShareOff)
set udg_t_godmode[5]=CreateTrigger()
call TriggerRegisterPlayerChatEvent(udg_t_godmode[5],udg_God,"-ally",false)
call TriggerAddAction(udg_t_godmode[5],function GM_Ally)
set udg_t_godmode[6]=CreateTrigger()
call TriggerRegisterPlayerChatEvent(udg_t_godmode[6],udg_God,"-enemy",false)
call TriggerAddAction(udg_t_godmode[6],function GM_Enemy)
set udg_t_godmode[7]=CreateTrigger()
call TriggerRegisterPlayerChatEvent(udg_t_godmode[7],udg_God,"-level",false)
call TriggerAddAction(udg_t_godmode[7],function GM_Level)
set udg_t_godmode[8]=CreateTrigger()
call TriggerRegisterPlayerChatEvent(udg_t_godmode[8],udg_God,"-vision",true)
call TriggerAddAction(udg_t_godmode[8],function GM_Vision)
set udg_t_godmode[9]=CreateTrigger()
call TriggerRegisterPlayerChatEvent(udg_t_godmode[9],udg_God,"-visionoff",true)
call TriggerAddAction(udg_t_godmode[9],function GM_VisionOff)
set udg_t_godmode[10]=CreateTrigger()
call TriggerRegisterPlayerChatEvent(udg_t_godmode[10],udg_God,"-destroyall",true)
call TriggerAddAction(udg_t_godmode[10],function GM_DestroyAll)
set udg_t_godmode[11]=CreateTrigger()
call TriggerRegisterPlayerChatEvent(udg_t_godmode[11],udg_God,"-reviveall",true)
call TriggerAddAction(udg_t_godmode[11],function GM_ReviveAll)
set udg_t_godmode[12]=CreateTrigger()
call TriggerRegisterPlayerChatEvent(udg_t_godmode[12],udg_God,"-day",true)
call TriggerAddAction(udg_t_godmode[12],function GM_Day)
set udg_t_godmode[13]=CreateTrigger()
call TriggerRegisterPlayerChatEvent(udg_t_godmode[13],udg_God,"-night",true)
call TriggerAddAction(udg_t_godmode[13],function GM_Night)
set udg_t_godmode[14]=CreateTrigger()
call TriggerRegisterPlayerEvent(udg_t_godmode[14],udg_God,EVENT_PLAYER_END_CINEMATIC)
call TriggerAddAction(udg_t_godmode[14],function GM_Cooldown)
set udg_t_godmode[15]=CreateTrigger()
call TriggerRegisterPlayerChatEvent(udg_t_godmode[15],udg_God,"-pe3komode",true)
call TriggerAddAction(udg_t_godmode[15],function GM_GodMode_Exit)
endfunction
Do I need to destroy these triggers? Set the actions into a variable?
I suppose this might be a bit off-topic but, did you make WarChasers? I played that map with a friend on LAN! We didn't even finish 1/4 of the map before we were killed, heh. I did take a look at the triggers (just looking! I thought it was an official map like BlizzardTD or Death Sheep! I was just curios) and I noticed those trap triggers. I thought they looked easy to code, easier than some of the Damage Area with Dummy I have seen here and there. Knowing that it's your trigger now... should I refrain from using it in my own maps or give you credit somehow? (Tbh when I first started making my own traps my thoughts were similar but I wasn't able to make it work.)I think you'd have to be spawning at least a million units over time to notice an issue. Possibly millions, but I haven't got time to test that as my computer won't support more than 1000 created units at a time.
Most lag will be caused by corpse decay and the blood splatter of exploded units. The corpse decay was such a problem for me in WarChasers 2 that I set the decay time to 12 seconds or something.
In a lot of cases you can use dummy recycling or not even need to create extra dummies in the first place (like having one dummy caster for most tasks).
I checked the triggers and maybe I was a bit inefficient with the group creating.Where do you set the group ?
^You need to set the bj before, not after![]()
Blimey! I didn't know it was such a big leak! Thanks for telling me! I will edit that ASAP.You can either :
- use 1 location variable for each player, but you have to put the following line into a "map initialization" trigger.
- or use only 1 location variable for all, but you have to remove the location every time.
Set TempLoc = (Center of ReviveStone1 <gen>)
The important thing is that the actions that create a location ("Center of region", "Polar position", "Target location of spell", etc...) are not fired too often compared to the action that clears the leak ("RemoveLocation"). In your trigger right there, there is 1 location created every time the trigger fires.
"Center of Region" always create a new location, regardless a location with the same coordinates has already been used before.
OK, thanks for clarifying.That's correct. However, strictly speaking, you don't destroy the variable, but the location.
Yes I'm a pain![]()
What are you talking about ?If you set Point as a unit, then to destroy it you use Location
But if the point is set on center of region, do you need Rect to destroy it?
I don't understand.
And ehh, I can't figure out difference between nulling and destroying. Could someone clarify that for me?
Just don't bother with nullifying variables if you do not use local variables.
I believe if you use global variables, then you will inevitably change their values to some other objects or just leave them alone. Now, if you set a global variable, it will decrease reference count to old value of the variable, and increase reference count of the new value, fixing the leak. So to say, you will always have as many variables not nulled, as you have global variables in total, and as many leaks. That's too small of a reason to worry about nullifying global variables.
Just wondering; how can a global pointer ever be leaked? A pointer is just a memory adress. As soon as the pointer/memory adress gets overwritten (which is the nature of globals, unless you never use this global again), the old pointer is gone.Globals leak the pointer, better to null them also. The leak is really minor.
Hmm, I'm not sure wether I got you right.Maker just meant that global pointers keep agents from freeing their id and in case you do not reuse it.
Yes. I was more talking about the integer square thing.Hashtables are flushable (+every cell remains selectable). Unless you lose the hashtable object, they do not leak either in theory. But practically you might refrain from doing so. Also integer size squared is enough to kill everything.
When I assign a global variable to a unit and the unit is removed, but I never null/overwrite the global variable, is the GetHandleId() of that unit never put back to the handle id stack?
If so, what would WC3 do in case the unit handle stack is depleted?
I'm curious; i never heard of that before.
Didn't ID pools have unique ranges depending on the type of handle? I recall them all being in the same range, like floating texts being 0-99 (okay, bad example, as floating texts do not extend handle, but you get the idea).The id pool can deplete? Well, of course, you can crack the integer limit. I think it throws an insufficient memory fatal even before.
Right, I confused that with something else.Array bounds are 0-8190/8191 (last index is bugged).
Interesting. However, I can't come up with a practical example where this could ever be a problem except with incrementing keys, so basicly, we come back to the point where we can say that nulling globals is never neccessary (except for hashtables).edit: But it's difficult to achieve a lot of unfreed ids with globals alone, maybe with hashtable entries.
Didn't ID pools have unique ranges depending on the type of handle? I recall them all being in the same range, like floating texts being 0-99 (okay, bad example, as floating texts do not extend handle, but you get the idea).
There are only very few client-async agents in the game. I think images and floating texts and that's about it.Yes but only agents are reference-counted and they lie in the same range.
Clearing/Not clearing a global could be a problem in case you work with client-async agents because it's another possibility to desync the id pool. Though this scenario is dangerous in the first place.
This would only work if we assume that the handle stack simply takes the next handle ID from the stack. But that isn't the case, for some reason.Images, Texttags are not agents. They have their custom id ranges, therefore do not pose a problem. My point was that you can create units and co. in an async manner IF you avoid all false transmissions. For example it should be possible to create a special effect for one player and fill the missing id with a location for the other player. Then when releasing the effect, you should do so too for the location.
if (GetLocalPlayer() == Player(0)) then
call DestroyEffect(e)
set e = null
else
call RemoveLocation(l)
endif
IsQuestCompleted
are actually superfluous. You set this attribute yourself, so you should avoid determining a sync decision from it. For all I care, such functions could be removed but this would break backwards compatibility. Having those types in the upper id pool makes them async-unfriendly although it would make sense to have them for specific clients. If you could create them locally, this would also benefit performance.That agents should not be destroyed or created inside local code is nothing new and only logical. I don't really see a problem with that and your example doesn't prove anything here because the desync is not caused by a global variable leaking a reference, but actual differences in IDs due to local creation of agents.Ex:
Code:if (GetLocalPlayer() == Player(0)) then call DestroyEffect(e) set e = null else call RemoveLocation(l) endif
local effect e = AddSpecialEffect(bla)
call DestroyEffect(e)
if (GetLocalPlayer() == Player(0)) then
set e = null
endif
I don't really see a problem with that and your example doesn't prove anything here because the desync is not caused by a global variable leaking a reference, but actual differences in IDs due to local creation of agents.
If what you said about reference count is correct, then this should cause a desync as soon as a new effect is created.
Because the reference count of the special effect is zero for Player(0) but 1 for Player(1), which should prevent the ID from being put back to the stack.
However, I did a quick test and this did not desync for me.
1) effects leak memory even when destroyed properly, which means that there HAS to be a reference to that effect somewhere in the WC3 code, no matter what the reference count is. Which basicly renders the whole argumentation of IDs not getting freed when there is a reference somewhere pointless
2) References to removed agents do not get freed in the game memory (hence they leak memory), but still reduce the reference count
3) As soon as an ID is allocated again, the pointer to that removed agent becomes a nullpointer