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

Infinite Visibility Modifiers?

Status
Not open for further replies.
Level 4
Joined
Mar 30, 2018
Messages
76
Hi guys, i want to ask you some help about how visibility modifiers works:

Does unlimited Visibility Modifiers could cause bugs/malfunctions/ weight on the RAM?

In my project i need special visibility circumstances: i need to have a permanent black mask above the whole map, but i also need to have permanent visibility above the already explored map areas, even if i don't have units in those areas.

So i've created those 2 small triggers that work correctly for my purpose, but i suspect they could weight on RAM or become buggy due their massive repetition.

Those are the triggers i've designed:

vis1.jpg
vis2.jpg
 
Level 9
Joined
Jul 30, 2018
Messages
445
Yep, just disable Fog of War and enable Black Mask. You can do these in the triggers, so player can't change it in the game options before launching the game. Also, note that you have to uncheck "Masked areas are partially visible" from Scenario -> Options for the visibility modifiers to take effect.
 
Level 4
Joined
Mar 30, 2018
Messages
76
Yeah this simple system works, aniway it causes some other complication related to generic gameplay of my map. What if i maintain the triggers i've showed? could they cause problems i've mentionend?
 
Level 9
Joined
Jul 30, 2018
Messages
445
Well, yeah. I would guess it can get a bit rough after some time, at least if the map is played for a long time. Though I'm not an expert on that field. Why isn't just disabling of Fog of War enough?
 
Level 4
Joined
Mar 30, 2018
Messages
76
Well, yeah. I would guess it can get a bit rough after some time
What do you mean by rough?


Though I'm not an expert on that field.
Can you suggest me someone to ask in particular?


Why isn't just disabling of Fog of War enough?
The answer is complex, but in summary I need the fog of war to be active, because it must hide some units from the minimap even while they are in a visible area, and under my control.
 
Level 11
Joined
Jul 4, 2016
Messages
626
Constantly creating them without setting them to a variable and destroying them when no longer needed will result in a leak. If massive repeatedly like you mentioned, may result in fps drops over time. You may want to create them only once in explored areas and disable and enable as needed for better efficiency.
 
Level 9
Joined
Jul 30, 2018
Messages
445
What do you mean by rough?

That, that it will be hard of the machine, I'd guess. And I don't know who would know better. Hopefully someone else here.



The answer is complex, but in summary I need the fog of war to be active, because it must hide some units from the minimap even while they are in a visible area, and under my control.

Well, try to think of some events that don't fire so often. Like, when a unit enters a region, then reveal a certain area, or something. I have a hard time figuring out a situation where you have to actually track so many smart orders from a player... :eek:
 
Level 4
Joined
Mar 30, 2018
Messages
76
Is there a way to activate/deactivate units minimap display via trigger? That would solve my problem. Currently i do this by applying/removing an ability that gives to those units -2000 sight radius, then when i find those unit by exploring, i remove from them those ability via triggers. Since the fog of war is active, they are not showed in the minimap becouse "they can't see themself", since their complexive sight radius is negative ;) but in this way i need to keep the triggers i've showed.
 
Level 9
Joined
Jul 30, 2018
Messages
445
Oh, so your plan is to hide unit minimap display? Just make two copies of a unit, other one has "Hide Minimap Display" set to true and other one has it set to false. Then when you find the unit, just replace the unit with the unit that has it set to false.
 
Last edited:
Level 4
Joined
Mar 30, 2018
Messages
76
try to check it does not triggers 12 times if you give order smart with 12 units at once.
Yeah you are right, i've checked via a message display, and that's why i've created the second trigger that disables the first one when it is fired once. the main trigger fires only once even with multiple units selected.

My project has some problems, after 25 -30 minutes of game it crashes due to memory usage that increases from 800 Mb to 1350 MB.

That means that the memory is leaking away.

Considering that i can't understand why the game doesn't use the whole 2Gb dedicated, i've worked for more than 1 year on removing the leaks via variables on unit groups, locations and special effects, everything that could leak is correctly structured via GUI, then the problem must be something else.

For testing purposes, i've created a trigger that spawns 25 different units with different models associated (obviously removing their location via GUI); each timethe trigger is fired, it removes the previous 25 units and creates 25 new random units. When the trigger is fired multiple (8 -10) times, the game crashes due to memory usage. this happens because each time, the memory usage increases by 100Mb!!! obviously that's not a problem of points leaking, since if this trigger was not correctly created it could not take so much memory for 25 points inside the map.
Really don't understanding the problem :/
 
Level 38
Joined
Feb 27, 2007
Messages
4,951
it removes the previous 25 units and creates 25 new random units.
Are you using "replace unit"? That particular function (and also many GUI functions) have a type of memory leak that you really can't do anything about unless you're willing to switch to JASS. Take a look at the function below:
JASS:
//===========================================================================
// This attempts to replace a unit with a new unit type by creating a new
// unit of the desired type using the old unit's location, facing, etc.
//
function ReplaceUnitBJ takes unit whichUnit, integer newUnitId, integer unitStateMethod returns unit
    local unit    oldUnit = whichUnit
    local unit    newUnit
    local boolean wasHidden
    local integer index
    local item    indexItem
    local real    oldRatio

   // If we have bogus data, don't attempt the replace.
    if (oldUnit == null) then
        set bj_lastReplacedUnit = oldUnit
        return oldUnit
    endif

   // Hide the original unit.
    set wasHidden = IsUnitHidden(oldUnit)
    call ShowUnit(oldUnit, false)

   // Create the replacement unit.
    if (newUnitId == 'ugol') then
        set newUnit = CreateBlightedGoldmine(GetOwningPlayer(oldUnit), GetUnitX(oldUnit), GetUnitY(oldUnit), GetUnitFacing(oldUnit))
    else
        set newUnit = CreateUnit(GetOwningPlayer(oldUnit), newUnitId, GetUnitX(oldUnit), GetUnitY(oldUnit), GetUnitFacing(oldUnit))
    endif

   // Set the unit's life and mana according to the requested method.
    if (unitStateMethod == bj_UNIT_STATE_METHOD_RELATIVE) then
       // Set the replacement's current/max life ratio to that of the old unit.
       // If both units have mana, do the same for mana.
        if (GetUnitState(oldUnit, UNIT_STATE_MAX_LIFE) > 0) then
            set oldRatio = GetUnitState(oldUnit, UNIT_STATE_LIFE) / GetUnitState(oldUnit, UNIT_STATE_MAX_LIFE)
            call SetUnitState(newUnit, UNIT_STATE_LIFE, oldRatio * GetUnitState(newUnit, UNIT_STATE_MAX_LIFE))
        endif

        if (GetUnitState(oldUnit, UNIT_STATE_MAX_MANA) > 0) and (GetUnitState(newUnit, UNIT_STATE_MAX_MANA) > 0) then
            set oldRatio = GetUnitState(oldUnit, UNIT_STATE_MANA) / GetUnitState(oldUnit, UNIT_STATE_MAX_MANA)
            call SetUnitState(newUnit, UNIT_STATE_MANA, oldRatio * GetUnitState(newUnit, UNIT_STATE_MAX_MANA))
        endif
    elseif (unitStateMethod == bj_UNIT_STATE_METHOD_ABSOLUTE) then
       // Set the replacement's current life to that of the old unit.
       // If the new unit has mana, do the same for mana.
        call SetUnitState(newUnit, UNIT_STATE_LIFE, GetUnitState(oldUnit, UNIT_STATE_LIFE))
        if (GetUnitState(newUnit, UNIT_STATE_MAX_MANA) > 0) then
            call SetUnitState(newUnit, UNIT_STATE_MANA, GetUnitState(oldUnit, UNIT_STATE_MANA))
        endif
    elseif (unitStateMethod == bj_UNIT_STATE_METHOD_DEFAULTS) then
       // The newly created unit should already have default life and mana.
    elseif (unitStateMethod == bj_UNIT_STATE_METHOD_MAXIMUM) then
       // Use max life and mana.
        call SetUnitState(newUnit, UNIT_STATE_LIFE, GetUnitState(newUnit, UNIT_STATE_MAX_LIFE))
        call SetUnitState(newUnit, UNIT_STATE_MANA, GetUnitState(newUnit, UNIT_STATE_MAX_MANA))
    else
       // Unrecognized unit state method - ignore the request.
    endif

   // Mirror properties of the old unit onto the new unit.
   //call PauseUnit(newUnit, IsUnitPaused(oldUnit))
    call SetResourceAmount(newUnit, GetResourceAmount(oldUnit))

   // If both the old and new units are heroes, handle their hero info.
    if (IsUnitType(oldUnit, UNIT_TYPE_HERO) and IsUnitType(newUnit, UNIT_TYPE_HERO)) then
        call SetHeroXP(newUnit, GetHeroXP(oldUnit), false)

        set index = 0
        loop
            set indexItem = UnitItemInSlot(oldUnit, index)
            if (indexItem != null) then
                call UnitRemoveItem(oldUnit, indexItem)
                call UnitAddItem(newUnit, indexItem)
            endif

            set index = index + 1
            exitwhen index >= bj_MAX_INVENTORY
        endloop
    endif

   // Remove or kill the original unit.  It is sometimes unsafe to remove
   // hidden units, so kill the original unit if it was previously hidden.
    if wasHidden then
        call KillUnit(oldUnit)
        call RemoveUnit(oldUnit)
    else
        call RemoveUnit(oldUnit)
    endif

    set bj_lastReplacedUnit = newUnit
    return newUnit
endfunction
Every time this function runs it 'leaks' 3 handle variable that have not been nulled (for example set newUnit = null) before the function returns. In this case we leak: oldUnit, newUnit, and indexItem. It's my understanding that by not nulling the variables the units'/items' handle IDs are never recycled and some memory relating to that object stays in use even if the object itself is totally removed from the map. In this case it's nearly impossible to avoid leaking newUnit because that variable has to be returned at the end of the function and so can't be nulled before or after that.

There are some leaks you can't do anything about, including some memory that's always eaten by a unit. Read the "things that always leak" part of this thread: Memory Leaks
 
Level 4
Joined
Mar 30, 2018
Messages
76
Are you using "replace unit"? That particular function (and also many GUI functions) have a type of memory leak that you really can't do anything about unless you're willing to switch to JASS. Take a look at the function below

Thank you for your complete explanation! Unfortunately i'm not prepared with Jass, even if i tried many times in the last 5 years of work :/ Anyway no,i 'm not replacing units but creating them on a global variable that i always remove via "RemoveLocation()" funcion


Anyway i'm sure that the problem isn't related to point leaking memory since each point leaks something like 1.6 Kb of memory, if my trigger was leaking some positions it could leak something like (1.6 * 25) Kb, that obviously is much less than 100 Mb.

i've loaded a lot of hi-res custom assets in game that has been associated to units spawned by the trigger in question. I understand that graphics require RAM,but can't understand why the RAM usage doesn't drop down if those models are removed from the map, usually players can experience lags or stutter if a game has something like 500+ simultaneous units in a melee game, but when those units die or are removed, the RAM usage is restored normally. this doesn't happen in my progect :/
 
Level 14
Joined
Sep 28, 2011
Messages
968
Did you try adding and removing all those units with one leak-less trigger and having no other trigger?
then you add back triggers slowly and see if placing and removing the units gives problems and once it does you know the problem trigger.
 
Status
Not open for further replies.
Top