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

[GUI-friendly] Aura System

This bundle is marked as awaiting update. A staff member has requested changes to it before it can be approved.
  • Like
Reactions: Spellbound
Any Ability Aura Multiple v3.1.0

Facilitates the creation of multiple auras which give abilities to units, or trigger custom events.



Any Ability Aura Multiple

Unnamed tab 2


What this system will give you:
A simple way to make custom auras that can have almost any effect you wish for. These auras can be based on any aura ability in the object editor, and they will function exactly like default auras work in-game (except for their effects).

The effects of this custom auras can be any ability you want (well, the ones wc3 allows you :) ), or you can do a lot more using the custom events provided to run code for your custom aura effect (examples in the testmap)

The targets you want to be affected can be easily determined in the aura's object editor data, or you can filter out more specific targets by filtering targets or using custom events to remove the aura effects from targets you do not want it to affect.

A very small amount of resources is needed to run this system, and it is optimized to consume as little as possible (if there are no units with na aura in the map, no checks will be run for that aura in the periodic trigger, thus you only process what you really need). Of course, if you have A LOT of units in your map and a large amount of auras, some loss of performance can occur.

Another optimization is that there are two periodic triggers, designed to require the least amount of resources depending on how many units there are in your map. When the ammount of units goes below or above a certain threshold, the system will switch between the two periodic triggers.


The system runs almost entirely on the backround, removing any leaks automatically with it's own CleanUP system. The only time you WILL need to run special code is when you add a custom aura ability to a unit through triggers, or when a unit transforms to another unit that has custom auras, and it didn't have those auras before. (see special operations section)

The test hap has been tested with 8000+ footmen, which reduced my fps from 60 to 50. At ~6000 there was no noticeable performance decrease. Number of auras was 5.

Unfortunately, Warcraft 3 auras consume resources, so getting 500+ units with auras is going to greatly affect performance.​

Advantages and system limitations:
Pros:
-Consumes very little memory
-If you only have around 1000 units in your map at a time, you should be able to support over 40 aura types at the same time.
-Easy configuration​
Cons:
-Auras can only have one level, so it is better used for items and unit auras
-You can make multiple level auras, but they will consume resources equivalent to 3 auras
-The more units you have, the less aura types you can support at the same time​

Aura Source = Unit that has an aura Ability (may or may not be a target).
Aura Target = Unit that has an aura Buff
Cycle Array = A variable unit array that contains all the units that are being checked for aura buffs

-Any unit that enters the map and meets user-defined conditions is added to the Cycle Array
-A periodic trigger fires every 0.3 seconds, checking every unit in the Cycle Array:
Adds abilties to the units, if they have the aura buff
Removes abilities from units, if they do not have the buff​
-The number of units with Auras is counted by the system, so the periodic triggers will only check for auras that are active


Importing:

How to import:

Easy method

Harder method that allows better customization


1.Open the World Editor
2. File->Preferences-> Tick the box for "Automatically create unkown variables while pasting trigger data"
3.Copy all triggers in the "Any Ability Aura Multiple 3" category to your map
4.Copy the ability "AAAM3GroupAbil" to your map.
5.Set the variable "AAAM3_GROUPABIL" variable to your newly copied ability int he trigger "AAAM3 Setup"


UNDER CONSTRUCTION

After you have deleted what you don't need, you can follows the steps in the easy method.


UNDER CONSTRUCTION (The guide might be a bit lacking here)



Configurable Settings: GUI

Note: If you want to change the frequency of the periodic checks, the events are added in the "AAAM3 Setup" Trigger.

How to add a new aura: Video (for version 2.0, slight diference in this version)

1. Open Trigger Editor and select "AAAM Setup" trigger
2. Increase the "Aura_Number" variable by 1
4. Copy and paste one of the templates of auras (only spellbook-based abilities need to be disabled for all players)
5. Increase all the variable indexes of your pasted template to the appropriate number
6. Change all values of variables in your pasted index to reflect the values of your new aura. Just follow the guidelines in the Trigger Comment


How to configure which units enter the CycleArray:
Note: Units not in the array aren't affected by custom aura effects
Note: Structures are disabled by default and as an example


It's just a matter of adding conditions in two different places:

Trigger - "AAAM3 Process New Units"
Add your conditions to the first "if" in this trigger(don't touch "(Triggering Unit) Not Equal to (Last Replaced Unit)").

Trigger - "AAAM3 Setup"
Under the comment "Adding units to the Cycle array:":
Just go to the "if/then/else" inside the For Loop and add your conditions there :)



Custom Events:


Version 2.0.0 added optional custom events to the System. In version 3.0.0 the events are built-in.

Events include:
-When the periodic trigger cycle begins running (no units have been checked) (0.3)
-When a unit is being checked in the periodic trigger for aura buffs (0.1)
-When a unit gains an aura buff (aura number)
-When a unit loses an aura buff (aura number + number of auras + 1)
-When a loses ALL aura buffs (0.5)​
-When a unit finishes being checked (0.2)​
-When the periodic trigger cycle finishes (all units have been checked) (0.4)


The event will fire for units that are aura sources. If you don't want to do anything if the unit is an aura source, just add the following condition to your trigger:

  • (Level of (Aura_AURAS[index]) for (Aura_TrigUnit)) Equal to 0
If you change "Equal to" to "Not Equal to", it will only execute the actions when an aura source gains the aura buff (if it already was under effect of the aura when it gained the aura, the actions will not exectue)

The test map comes with 2 examples of coding-enhanced auras, please analyze them for a better understanding of the system. For a guide to the events, see the trigger comment in the trigger "AAAM Periodic Event"



Operations Limit:
The warcraft engine only runs a limited number of operations per thread (a thread is usually a trigger or a ForGroup loop). So if you have too many auras and too many units, you may reach the Operations Limit for this system, causing the trigger to stop working.

In order to avoid this, change the variable "AAAM3_CycleStep" in the "AAAM3 Setup" trigger. The default step of 800 can handle 5 auras and 8000+ units in the CycleArray with some leeway, so you might not have to change this. To be safe, you can use the formula:
CycleStep = [Number of Units Expected] / ([Number of Auras]*2)

You can change CycleStep during the game, but make sure that the event variable is equal to 0.4 when you do.

Special operations:
Note: if you do these without calling the custom script the aura won't work
Version 3.0.0 has made all garbage cleanup automatic




Add any auras you want to the unit
  • Set AAAM3_CycleArray[0] = your_unit
  • Trigger - Run AAAM3 Add Source <gen> (ignoring conditions)

Test Map:

Auras Included in the test map:
  • Armor Aura
  • Damage Aura
  • Critical Strike Aura (currently also gives units shadowmeld for easy testing)
  • Negate Damage Aura
  • Hero Stats Aura
Custom event example 1: Damage Aura will kill nearby units after 2 and revive them (if they are heroes).
Custom event example 2: Armor Aura will give nearby units flying height.

Test map commands:
-spawn (spawns 100 mountain kings with an aura item)
-spawn2 (spawns 12 rifleman with an aura)
-spawnf (spawns 100 footmen with no aura)
-start (Unhide all the footmen in the map (when they die, they are hidden again))
-add ability (adds damage aura to selected units)
-remove ability (removes damage aura from selected units)
-size (currently does nothing)
-kill (kills selected units)
-example1/example2 on/off (turns on the included examples for trigger-enhanced auras)


Code:

Triggers:

Unnamed tab 1

SETUP

Add Source

Cleanup

Periodic

  • AAAM3 Setup
    • Events
      • Time - Elapsed game time is 0.00 seconds
    • Conditions
    • Actions
      • -------- ----- --------
      • -------- SETTINGS START HERE --------
      • Set AAAM3_GROUPABIL = AAAM3GroupAbil
      • -------- Adding Events to periodic JASS triggers --------
      • -------- - --------
      • Trigger - Add to AAAM Periodic Instant <gen> the event (Time - Every 0.30 seconds of game time)
      • Trigger - Add to AAAM Periodic Intervals <gen> the event (Time - Every 0.03 seconds of game time)
      • -------- - --------
      • -------- Set this to the highest ability index --------
      • Set Aura_Number = 4
      • -------- - --------
      • -------- If you're only using 1 Periodic trigger, than delete this setting --------
      • Trigger - Turn off AAAM Periodic Intervals <gen>
      • -------- - --------
      • -------- If you are hitting the operation's limit, reduce this number --------
      • -------- - --------
      • Set AAAM3_CycleStep = 800
      • -------- - --------
      • -------- Adding units to Cycle array (add your conditions here) --------
      • For each (Integer A) from 1 to 16, do (Actions)
        • Loop - Actions
          • Unit Group - Pick every unit in (Units owned by (Player((Integer A)))) and do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ((Picked unit) is A structure) Equal to False
                • Then - Actions
                  • Set Aura_CycleSize = (Aura_CycleSize + 1)
                  • Set AAAM3_CycleArray[Aura_CycleSize] = (Picked unit)
                  • Unit - Add AAAM3_GROUPABIL to (Picked unit)
                • Else - Actions
              • Set AAAM3_CycleArray[0] = (Picked unit)
              • Trigger - Run AAAM3 Add Source <gen> (ignoring conditions)
      • -------- - --------
      • -------- AURAS --------
      • Set Aura_AURAS[0] = ZZDamage Aura
      • Set Aura_BUFFS[0] = ZZDamage Aura
      • Set Aura_ABILITIES[0] = AAAM3|Buff_Damage
      • -------- - --------
      • Set Aura_AURAS[1] = ZZArmor Aura
      • Set Aura_BUFFS[1] = ZZArmor Aura
      • Set Aura_ABILITIES[1] = AAAM3|Buff_Armor
      • -------- - --------
      • Set Aura_AURAS[2] = ZZCritical Strike Aura
      • Set Aura_BUFFS[2] = ZZCritical Strike Aura
      • Set Aura_ABILITIES[2] = AAAM3|Spbk_Critical Strike
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • Player - Disable Aura_ABILITIES[2] for (Picked player)
      • -------- - --------
      • Set Aura_AURAS[3] = ZZNegate Damage Aura
      • Set Aura_BUFFS[3] = ZZNegate Damage Aura
      • Set Aura_ABILITIES[3] = AAAM3|SpBk_Negate Damage
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • Player - Disable Aura_ABILITIES[3] for (Picked player)
      • -------- - --------
      • Set Aura_AURAS[4] = ZZStats Aura
      • Set Aura_BUFFS[4] = ZZStats Aura
      • Set Aura_ABILITIES[4] = AAAM3|Buff_Stats
      • -------- - --------
      • -------- SETTINGS END HERE --------
      • -------- - --------
      • -------- Define Hashtable Values --------
      • Set AAAM3_CycleArray[Aura_CycleSize] = No unit
      • -------- Defining Cycle Interval --------
      • Set AAAM3_CycleMax = Aura_CycleSize
      • Set AAAM3_CycleMin = 1
      • Set AAAM3_newIndex = 1
  • AAAM3 Add Source
    • Events
    • Conditions
    • Actions
      • Custom script: local integer store_J = udg_AAAM3_J
      • For each (Integer AAAM3_J) from 0 to Aura_Number, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Level of Aura_AURAS[AAAM3_J] for AAAM3_CycleArray[0]) Not equal to 0
              • (AAAM3_CycleArray[0] is in Aura_SourceGroup[AAAM3_J]) Equal to False
            • Then - Actions
              • Set Aura_AuraCount[AAAM3_J] = (Aura_AuraCount[AAAM3_J] + 1)
              • Unit Group - Add AAAM3_CycleArray[0] to Aura_SourceGroup[AAAM3_J]
            • Else - Actions
      • Custom script: set udg_AAAM3_J = store_J

  • AAAM3 Clean SourceGroups
    • Events
      • Game - Aura_Event becomes Equal to 0.30
    • Conditions
    • Actions
      • Custom script: local unit udg_Aura_TrigUnit
      • Custom script: local group udg_temp_group
      • Custom script: local integer udg_AAAM3_i
      • Custom script: local integer udg_AAAM3_J
      • For each (Integer AAAM3_J) from 0 to Aura_Number, do (Actions)
        • Loop - Actions
          • Set Aura_AuraCount[((AAAM3_J + Aura_Number) + 1)] = 0
          • Custom script: set udg_temp_group = CreateGroup()
          • For each (Integer AAAM3_i) from 1 to Aura_AuraCount[AAAM3_J], do (Actions)
            • Loop - Actions
              • Custom script: set udg_Aura_TrigUnit = FirstOfGroup(udg_Aura_SourceGroup[udg_AAAM3_J])
              • Unit Group - Remove Aura_TrigUnit from Aura_SourceGroup[AAAM3_J]
              • Custom script: if not IsUnitType(udg_Aura_TrigUnit , UNIT_TYPE_DEAD) and GetUnitTypeId(udg_Aura_TrigUnit) != 0 and GetUnitAbilityLevel( udg_Aura_TrigUnit , udg_Aura_AURAS[udg_AAAM3_J]) != 0 then
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                • Then - Actions
                  • Unit Group - Add Aura_TrigUnit to temp_group
                  • Custom script: else
                  • Custom script: endif
                • Else - Actions
                  • Set Aura_AuraCount[((AAAM3_J + Aura_Number) + 1)] = (Aura_AuraCount[((AAAM3_J + Aura_Number) + 1)] + 1)
          • Custom script: call DestroyGroup(udg_Aura_SourceGroup[udg_AAAM3_J])
          • Set Aura_SourceGroup[AAAM3_J] = temp_group
      • Countdown Timer - Start AAAM3_Timer as a One-shot timer that will expire in 3.00 seconds
      • Custom script: set udg_temp_group = null
      • Custom script: set udg_Aura_TrigUnit = null
      • Trigger - Turn off (This trigger)
  • AAAM3 Clean Timer
    • Events
      • Time - AAAM3_Timer expires
    • Conditions
    • Actions
      • Custom script: local integer udg_AAAM3_J
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Aura_AuraCount[(Aura_Number + (Aura_Number + 1))] Not equal to 1
        • Then - Actions
          • For each (Integer AAAM3_J) from 0 to Aura_Number, do (Actions)
            • Loop - Actions
              • Set Aura_AuraCount[AAAM3_J] = (Aura_AuraCount[AAAM3_J] - Aura_AuraCount[((AAAM3_J + Aura_Number) + 1)])
              • Countdown Timer - Start AAAM3_Timer as a One-shot timer that will expire in 7.00 seconds
          • Set Aura_AuraCount[(Aura_Number + (Aura_Number + 1))] = 1
        • Else - Actions
          • Trigger - Turn on AAAM3 Clean SourceGroups <gen>
          • Set Aura_AuraCount[(Aura_Number + (Aura_Number + 1))] = 0

  • AAAM3 Change Period Type
    • Events
      • Game - AAAM3_LimitChecker becomes Greater than 3000.00
      • Game - AAAM3_LimitChecker becomes Less than or equal to 3000.00
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • AAAM3_LimitChecker Greater than 3000.00
        • Then - Actions
          • Trigger - Turn off AAAM Periodic Instant <gen>
          • Trigger - Turn on AAAM Periodic Intervals <gen>
        • Else - Actions
          • Trigger - Turn off AAAM Periodic Intervals <gen>
          • Trigger - Turn on AAAM Periodic Instant <gen>
JASS:
function AAAMPeriodicWE takes nothing returns boolean
    local integer i = 0
    local integer j = 0
    local integer newIndex = udg_AAAM3_newIndex
    local boolean leave = true
    local integer store_i
    local integer array validAuras
    local integer max
    loop
    exitwhen i > udg_Aura_Number
        if udg_Aura_AuraCount[i] > 0 then
            //call BJDebugMsg(I2S(j))
            set validAuras[j] = i
            set j = j + 1
            //call BJDebugMsg(I2S(i))
        endif
        set i = i + 1
    endloop
    set max = j - 1
    set i = 0
    set j = udg_AAAM3_CycleMin
    //call BJDebugMsg(I2S(udg_AAAM3_CycleMin))
    //call BJDebugMsg(I2S(udg_AAAM3_CycleMax))
    if udg_AAAM3_CycleMin == 1 then
        set udg_Aura_Event = 0.3 // Set Event for Starting a new cycle
    endif
    set udg_Aura_TrigUnit = udg_AAAM3_CycleArray[j]
    set udg_Aura_Event = 0.1 //Set Event for Starting checks for 1 unit
    loop
    exitwhen j > udg_AAAM3_CycleMax
    set udg_AAAM3_CycleArray[j] = null
        loop
        exitwhen i > max
            set store_i = i
            set i = validAuras[i]
            if GetUnitAbilityLevel(udg_Aura_TrigUnit, udg_Aura_BUFFS[i]) > 0  then
                if UnitAddAbility(  udg_Aura_TrigUnit , udg_Aura_ABILITIES[i] ) then
                    set udg_Aura_Event = i // Set event for unit aquiring aura ability
                endif
                set leave = false
            else
                if UnitRemoveAbility(  udg_Aura_TrigUnit , udg_Aura_ABILITIES[i] ) then
                    set udg_Aura_Event = 1 + udg_Aura_Number + i
                endif
            endif
            set i = store_i + 1
        endloop
    if not leave then
        set udg_AAAM3_CycleArray[newIndex] = udg_Aura_TrigUnit
        set newIndex = newIndex + 1
    else
        if not IsUnitType(udg_Aura_TrigUnit , UNIT_TYPE_DEAD) then
            if GetUnitTypeId(udg_Aura_TrigUnit) == 0 then
            else
            set udg_AAAM3_CycleArray[newIndex] = udg_Aura_TrigUnit
            set newIndex = newIndex + 1
            endif
        else
            call UnitRemoveAbility ( udg_Aura_TrigUnit , udg_AAAM3_GROUPABIL )
        endif
        set udg_Aura_Event = 0.5 //Set Event for unit being kicked out of the CycleAraay
    endif
    set udg_Aura_Event = 0.2 // Set Event for unit checks are finished
    set j = j + 1
    set udg_Aura_TrigUnit = udg_AAAM3_CycleArray[j]
    set leave = true
    set i = 0
    set udg_Aura_Event = 0.1 //Set Event for unit checks begin for next unit
    endloop

 
 

    //call BJDebugMsg("Cycle Size: " + I2S(udg_Aura_CycleSize))
    if udg_AAAM3_CycleMax + udg_AAAM3_CycleStep < udg_Aura_CycleSize then
        set udg_AAAM3_CycleMin = udg_AAAM3_CycleMax+1
        set udg_AAAM3_CycleMax = udg_AAAM3_CycleMax + udg_AAAM3_CycleStep
        set udg_AAAM3_newIndex = newIndex
        //call TriggerEvaluate(GetTriggeringTrigger())
    else
        if udg_AAAM3_CycleMax < udg_Aura_CycleSize then
            set udg_AAAM3_CycleMin = udg_AAAM3_CycleMax+1
            set udg_AAAM3_CycleMax = udg_Aura_CycleSize
            set udg_AAAM3_newIndex = newIndex
            //call TriggerEvaluate(GetTriggeringTrigger())
 
        else
            if udg_Aura_CycleSize < udg_AAAM3_CycleStep then
                set udg_AAAM3_CycleMax = udg_Aura_CycleSize
            else
                set udg_AAAM3_CycleMax = udg_AAAM3_CycleStep
            endif
            set udg_AAAM3_CycleMin = 1
            set udg_AAAM3_newIndex = 1
            set udg_Aura_CycleSize = newIndex
            set udg_Aura_Event = 0.4 //Set Event for Cycle is finished
        endif
     endif
 
    return true
endfunction
//===========================================================================
function InitTrig_AAAM_Periodic_Intervals takes nothing returns nothing
    set gg_trg_AAAM_Periodic_Intervals = CreateTrigger(  )
    //call TriggerRegisterTimerEvent( gg_trg_AAAM_Periodic_Intervals, 0.03, true )
    call TriggerAddCondition( gg_trg_AAAM_Periodic_Intervals, Condition(function AAAMPeriodicWE) )
endfunction

JASS:
function AAAMPeriodicWE2 takes nothing returns boolean
    local integer i = 0
    local integer j = 0
    local integer newIndex = udg_AAAM3_newIndex
    local boolean leave = true
    local integer store_i
    local integer array validAuras
    local integer max
    loop
    exitwhen i > udg_Aura_Number
        if udg_Aura_AuraCount[i] > 0 then
            //call BJDebugMsg(I2S(j))
            set validAuras[j] = i
            set j = j + 1
        endif
        set i = i + 1
    endloop
    set max = j - 1
    set i = 0
    set j = udg_AAAM3_CycleMin
    //call BJDebugMsg(I2S(udg_AAAM3_CycleMin))
    //call BJDebugMsg(I2S(udg_AAAM3_CycleMax))
    set udg_Aura_Event = 0.3 // Set Event for Starting a new cycle
    set udg_Aura_TrigUnit = udg_AAAM3_CycleArray[j]
    set udg_Aura_Event = 0.1 //Set Event for Starting checks for 1 unit
    loop
    exitwhen j > udg_AAAM3_CycleMax
    set udg_AAAM3_CycleArray[j] = null
        loop
        exitwhen i > max
            set store_i = i
            set i = validAuras[i]
            if GetUnitAbilityLevel(udg_Aura_TrigUnit, udg_Aura_BUFFS[i]) > 0  then
                if UnitAddAbility(  udg_Aura_TrigUnit , udg_Aura_ABILITIES[i] ) then
                    set udg_Aura_Event = i // Set event for unit aquiring aura ability
                endif
                set leave = false
            else
                if UnitRemoveAbility(  udg_Aura_TrigUnit , udg_Aura_ABILITIES[i] ) then
                    set udg_Aura_Event = 1 + udg_Aura_Number + i
                endif
            endif
            set i = store_i + 1
        endloop
    if not leave then
        set udg_AAAM3_CycleArray[newIndex] = udg_Aura_TrigUnit
        set newIndex = newIndex + 1
    else
        if not IsUnitType(udg_Aura_TrigUnit , UNIT_TYPE_DEAD) then
            if GetUnitTypeId(udg_Aura_TrigUnit) == 0 then
            else
            set udg_AAAM3_CycleArray[newIndex] = udg_Aura_TrigUnit
            set newIndex = newIndex + 1
            endif
        else
            call UnitRemoveAbility ( udg_Aura_TrigUnit , udg_AAAM3_GROUPABIL )
        endif
        set udg_Aura_Event = 0.5 //Set Event for unit being kicked out of the CycleAraay
    endif
    set udg_Aura_Event = 0.2 // Set Event for unit checks are finished
    set j = j + 1
    set udg_Aura_TrigUnit = udg_AAAM3_CycleArray[j]
    set leave = true
    set i = 0
    set udg_Aura_Event = 0.1 //Set Event for unit checks begin for next unit
    endloop

 
     //Set Event for Cycle is finished

    //call BJDebugMsg("Cycle Size: " + I2S(udg_Aura_CycleSize))
    if udg_AAAM3_CycleMax + udg_AAAM3_CycleStep < udg_Aura_CycleSize then
        set udg_AAAM3_CycleMin = udg_AAAM3_CycleMax+1
        set udg_AAAM3_CycleMax = udg_AAAM3_CycleMax + udg_AAAM3_CycleStep
        set udg_AAAM3_newIndex = newIndex
        call TriggerEvaluate(GetTriggeringTrigger())
    else
        if udg_AAAM3_CycleMax < udg_Aura_CycleSize then
            set udg_AAAM3_CycleMin = udg_AAAM3_CycleMax+1
            set udg_AAAM3_CycleMax = udg_Aura_CycleSize
            set udg_AAAM3_newIndex = newIndex
            call TriggerEvaluate(GetTriggeringTrigger())
 
        else
            if udg_Aura_CycleSize < udg_AAAM3_CycleStep then
                set udg_AAAM3_CycleMax = udg_Aura_CycleSize
            else
                set udg_AAAM3_CycleMax = udg_AAAM3_CycleStep
            endif
            set udg_AAAM3_CycleMin = 1
            set udg_AAAM3_newIndex = 1
            set udg_Aura_CycleSize = newIndex
            set udg_Aura_Event = 0.4
        endif
     endif
 
    return true
endfunction
//===========================================================================
function InitTrig_AAAM_Periodic_Instant takes nothing returns nothing
    set gg_trg_AAAM_Periodic_Instant = CreateTrigger(  )
    //call TriggerRegisterTimerEvent( gg_trg_AAAM_Periodic_Instant, 0.3, true )
    call TriggerAddCondition( gg_trg_AAAM_Periodic_Instant, Condition(function AAAMPeriodicWE2) )
endfunction

  • AAAM Periodic GUI
    • Events
      • Time - Every 0.30 seconds of game time
    • Conditions
    • Actions
      • Custom script: local integer store_i
      • Custom script: local integer newIndex = 1
      • Custom script: local integer array validAuras
      • Set AAAM3_J = 0
      • For each (Integer AAAM3_i) from 0 to Aura_Number, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Aura_AuraCount[AAAM3_i] Greater than 0
            • Then - Actions
              • Custom script: set validAuras[udg_AAAM3_J] = udg_AAAM3_i
              • Set AAAM3_J = (AAAM3_J + 1)
            • Else - Actions
      • Set zzAura_GUI_Max = (AAAM3_J - 1)
      • Set Aura_Event = 0.30
      • For each (Integer AAAM3_J) from 1 to Aura_CycleSize, do (Actions)
        • Loop - Actions
          • Set zzAura_GUI_leave = True
          • Set Aura_TrigUnit = AAAM3_CycleArray[AAAM3_J]
          • Set Aura_Event = 0.10
          • Set AAAM3_CycleArray[AAAM3_J] = No unit
          • For each (Integer AAAM3_i) from 0 to zzAura_GUI_Max, do (Actions)
            • Loop - Actions
              • Custom script: set store_i = udg_AAAM3_i
              • Custom script: set udg_AAAM3_i = validAuras[store_i]
              • Custom script: if GetUnitAbilityLevel(udg_Aura_TrigUnit, udg_Aura_BUFFS[udg_AAAM3_i]) != 0 then
              • Set zzAura_GUI_leave = False
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Level of Aura_ABILITIES[AAAM3_i] for Aura_TrigUnit) Equal to 0
                • Then - Actions
                  • Unit - Add Aura_ABILITIES[AAAM3_i] to Aura_TrigUnit
                  • Set Aura_Event = (Real(AAAM3_i))
                • Else - Actions
                  • Unit - Add Aura_ABILITIES[AAAM3_i] to Aura_TrigUnit
              • Custom script: else
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Level of Aura_ABILITIES[AAAM3_i] for Aura_TrigUnit) Not equal to 0
                • Then - Actions
                  • Unit - Remove Aura_ABILITIES[AAAM3_i] from Aura_TrigUnit
                  • Set Aura_Event = (((Real(AAAM3_i)) + (Real(Aura_Number))) + 1.00)
                • Else - Actions
                  • Unit - Remove Aura_ABILITIES[AAAM3_i] from Aura_TrigUnit
              • Custom script: endif
              • Custom script: set udg_AAAM3_i = store_i
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • zzAura_GUI_leave Not equal to True
            • Then - Actions
              • Custom script: set udg_AAAM3_CycleArray[newIndex] = udg_Aura_TrigUnit
              • Custom script: set newIndex = newIndex + 1
            • Else - Actions
              • Set Aura_Event = 0.50
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Aura_TrigUnit is alive) Equal to True
                • Then - Actions
                  • Custom script: set udg_AAAM3_CycleArray[newIndex] = udg_Aura_TrigUnit
                  • Custom script: set newIndex = newIndex + 1
                • Else - Actions
                  • Unit - Remove AAAM3_GROUPABIL from Aura_TrigUnit
          • Set Aura_Event = 0.20
      • Custom script: set udg_Aura_CycleSize = newIndex
      • Set Aura_Event = 0.40


Updates:
version x.y.z

x->Major functionality change
y->Changes to the Code
z->Changes to the Testmap/templates

-Fixed some leftover BJs
-Removed condition from dynamic triggers, replaced by an event with boolexpr
-Action in periodic trigger replaced with condition
-AAAMRemSource function now return true if the unit had auras or false if it did not
-Added guide to replace aura units for new aura units
-Added example replace trigger in the map
-Created replace Boolean variable and a new integer variable (both are optional)

-Changed unit group "CycleGroup" to a unit array
-No longer saving source units in group variables
-As a result, the Group Refresh library is no longer needed
-As a result of item 2, system a bit faster (no fps drop at 3000+ target units)
-Added the option to have custom Events

Update 2.0.1: Fixed ZZGroupAbil spell to not add damage
[/color]

WIP

JASS:
function Nice takes nothing returns nothing
    local integer totalProcessed = 0
    local integer aId
    local unit u
    local integer i = 0
    local group newGroup
    loop
    exitwhen aId > udg_GAAS_Number
    exitwhen totalProcessed + udg_GAAS_GroupSize[aId]> 4000
        set newGroup = CreateGroup()
        loop
        exitwhen i > udg_GAAS_GroupSize[aId]
        set i = i + 1
        set udg_GAAS_TrigUnit = FirstOfGroup(udg_GAAS_Groups[aId])
        call GroupRemoveUnit(udg_GAAS_Groups[aId] , udg_GAAS_TrigUnit)
        if GetUnitAbilityLevel(udg_GAAS_TrigUnit , udg_GAAS_BUFF[aId]) < 0 then
            call UnitRemoveAbility(udg_GAAS_TrigUnit, udg_GAAS_ABIL[aId])
            set udg_GAAS_RemoveEvent = aId
            set udg_GAAS_GroupSize[aId] = udg_GAAS_GroupSize[aId] - 1
        else
            call GroupAddUnit(newGroup, udg_GAAS_TrigUnit)
        endif
        endloop
        call DestroyGroup(udg_GAAS_Groups[aId])
        set udg_GAAS_Groups[aId] = newGroup
        set totalProcessed = totalProcessed + udg_GAAS_GroupSize[aId]
        set aId = aId + 1
    endloop
    if aId > udg_GAAS_Number then
 
    else
        call ExecuteFunc("Nice")
    endif
 
endfunction

function GAAS_TimerF takes nothing returns nothing
    local integer runCount
    local timer t = GetExpiredTimer()
    local integer tHandle = GetHandleId(t)
    local integer aId = LoadInteger(udg_GAAS_Hashtable, tHandle, 1)
    local unit u = LoadUnitHandle(udg_GAAS_Hashtable, tHandle, 0)
 
    if GetUnitAbilityLevel(u , udg_GAAS_BUFF[aId] ) > 0 then
        call FlushChildHashtable(udg_GAAS_Hashtable, tHandle)
        call RemoveSavedHandle(udg_GAAS_Hashtable, GetHandleId(u) , aId)
 
        call PauseTimer(t)
        call DestroyTimer(t)
    else
        set runCount = LoadInteger(udg_GAAS_Hashtable, tHandle, 2) + 1
        call SaveInteger(udg_GAAS_Hashtable, tHandle, 2, runCount)
    endif
 
    set t = null
    set u = null
 
endfunction

function GAAS_EnterRange takes nothing returns boolean
    local unit source
    local unit target = GetTriggerUnit()
    local integer sourceHandle = GetHandleId(source)
    local integer targetHandle = GetHandleId(target)
    local integer aId = 0
 
    local timer t
    loop
    exitwhen aId > udg_GAAS_Number
        if LoadBoolean(udg_GAAS_Hashtable, aId, sourceHandle) and GetUnitAbilityLevel(target, udg_GAAS_AURA[aId]) > 0 then
            set t = LoadTimerHandle(udg_GAAS_Hashtable, targetHandle, aId)
            if t == null then
                set t = CreateTimer()
                call TimerStart(t, 0.1, true, function GAAS_TimerF)
                call SaveTimerHandle(udg_GAAS_Hashtable, targetHandle, aId , t)
                call SaveUnitHandle(udg_GAAS_Hashtable, GetHandleId(t), 0 , target)
                call SaveInteger(udg_GAAS_Hashtable, GetHandleId(t), 1 , aId)
                call SaveInteger(udg_GAAS_Hashtable, GetHandleId(t), 2 , 0)
 
            else
                call SaveInteger(udg_GAAS_Hashtable, GetHandleId(t), 2 , 0)
            endif
        endif
    endloop

    return false
endfunction


function GAAS_Source takes nothing returns nothing
 
    local trigger trig
    local boolean notSource =true
    local integer aId = 0
    local integer uHandle
    //call FlushChild
    loop
    exitwhen aId > udg_GAAS_Number
        if GetUnitAbilityLevel(udg_GAAS_TrigUnit, udg_GAAS_AURA[aId]) > 0 then
            set notSource = false
            if LoadBoolean(udg_GAAS_Hashtable, aId, uHandle) then
            else
                call SaveBoolean(udg_GAAS_Hashtable, aId, uHandle, true)
            endif
        else
            if LoadBoolean(udg_GAAS_Hashtable, aId, uHandle) then
                call RemoveSavedBoolean(udg_GAAS_Hashtable, aId, uHandle)
            endif
        endif
    endloop
    if notSource then
        call DestroyTrigger(LoadTriggerHandle(udg_GAAS_Hashtable, uHandle , udg_GAAS_Number + 1))
        call RemoveSavedHandle(udg_GAAS_Hashtable, uHandle , udg_GAAS_Number + 1)
    else
        if not HaveSavedHandle(udg_GAAS_Hashtable, uHandle , udg_GAAS_Number + 1) then
            set trig = CreateTrigger()
            call TriggerAddCondition(trig, Condition(function GAAS_EnterRange))
            call SaveTriggerHandle(udg_GAAS_Hashtable, uHandle , udg_GAAS_Number + 1, trig)
        endif
    endif
endfunction
//===========================================================================
function InitTrig_AAAM4_Period takes nothing returns nothing
    set gg_trg_AAAM4_Period = CreateTrigger(  )
endfunction
Contents

Any Ability Aura Multiple (Map)

Level 12
Joined
Jun 12, 2010
Messages
413
Uhh... why did you create another submission for this? There is an "Edit" button for a reason.


I made a few core changes that make this work pretty differently from the other system, but the other system still has a few advantages that makes it more effective in some situations, so I wanted to keep both. But I ran into some big problems with the other method, so I asked to have it sent to substandard until I figure it out.

Of course, if moderators think it's better to delete it until I get it fixed or have both systems in the same resource, I would happily comply too. It's in the description in red text (I was editing as you posted :S)


I can also change the name if you think it's too confusing/unorganized to have 2 versions with the same name
 
Level 12
Joined
Jun 12, 2010
Messages
413
Yeah I read that part, but I was confused as to why they both have the same exact name.


Is it enough to justify a second upload?


Well, if I can get the other one working, it will only cycle through relevant units, so performance should be fairly better in situations where units unaffected by auras highly outnumber units affected. That system however, supports less units with auras because they demand extra calculations/resources. The system currently works, but it bugs if a unit with an aura is silenced

This system cycles through all units in the map (except if you filter buildings or certain unit types or whatever you want, then those will not be considered). It also doesn't need map header JASS functions (it can be GUI only, but the GUI periodic trigger is so slow, I don't see the point). It also has an automatic leak deletion, but I think I could add that to the other system. Units with auras will consume basically just as much as a normal unit would (except by the resources that wc3 auras already take)

Sorry if that's not enough to warrant two versions, then this can be deleted and I'll just move it over to the other one and see what I'll do about the old version.

Though I agree that having the same name is a bit confusing now that I think about it :S
 
Level 12
Joined
Jun 12, 2010
Messages
413
Changing how efficient your system works doesn't call for a second upload. I can either delete one of them or move it to Simple / Substandard. Let me know what you want done, and to which resource.

Oh, if you can move it to simple/substandard, that would be better. Do it to the old one, please. If you think it's better to have it deleted, feel free to do so too, I've a backup of the mapfile and description.


EDIT: Actually, I think it's better to delete one of them. Can I switch over the description and the maps/images from this one to the old one? I reckon the replies there are more important than a discussion about a resource that's deleted anyway. It would be like I'd updated it.

EDIT: Well, disregard my edit. Already caused too much trouble
 
Last edited:
Level 12
Joined
Jun 12, 2010
Messages
413
UPDATE: Finally updated to version 3.1.0 , took a bit longer than I had expected xD

Changes:
Readded Groupabil from old version.
Made triggers a lot simpler, maintaining the same functionality (though add source may be a tad bit slower)
Things are a lot more readable and maintainable now
Hashtable variable is no longer required, it has now been deleted
I must say, the best description ever.
Why, thank you very much =3

EDIT: Oh no, I changed the title and it went to the top of submissions :S
 
Last edited:
Thanks for the submission and I apologize for it taking so long to get around to this system in the section, I have a few things I'd like to address in regards to it:
- What's the purpose of having both JASS and GUI periodic triggers? Couldn't the system be entirely in JASS and reduced to a single trigger? I furthermore don't entirely understand why all the GUI triggers aren't in JASS except the initialization one and all put into one trigger, lines upon lines of un-highlighted custom script is awkward to go through you know XD
- You have a group leak in your initialization (leaks 16 times)
- There's no point putting an empty else block in, just use endif by itself
- Use the not() function on boolean expressions if you would only use the else (you do this with if GetUnitTypeId(udg_Aura_TrigUnit) == 0 then)
- You have indentation errors in your JASS code, also stylistically I suggest spreading out logical blocks a bit more to make the code more readable
- There's a lot of obscure numbers for the event triggers and they're not exactly clear
- Your recycling method is odd, why cleanup every aura at once instead of de-allocating each one as necessary? It just seems really messy and well bad frankly
- Your recycle also is leaking many groups (tempGroup needs to be nulled every time before you use CreateGroup() again, not just at the end as groups are agents
- Also your last SourceGroup is never destroyed whenever you run the cleanup, while the number of these you "leak" never goes up, there's no need to be leaking any at all and I can't see any reason to not also clean that one up

For those reasons I'm going to set this to needs fix, I hope you have the time to fix up the system as it's quite a neat idea generally
The system appears otherwise sound from the things mentioned above though I'll obviously need to go through it again after changes have been made, oh thought I'd mention you left the WIP part of your description accidentally XD
 
Level 12
Joined
Jun 12, 2010
Messages
413
Thanks for the submission and I apologize for it taking so long to get around to this system in the section, I have a few things I'd like to address in regards to it:
- What's the purpose of having both JASS and GUI periodic triggers? Couldn't the system be entirely in JASS and reduced to a single trigger? I furthermore don't entirely understand why all the GUI triggers aren't in JASS except the initialization one and all put into one trigger, lines upon lines of un-highlighted custom script is awkward to go through you know XD
- You have a group leak in your initialization (leaks 16 times)
- There's no point putting an empty else block in, just use endif by itself
- Use the not() function on boolean expressions if you would only use the else (you do this with if GetUnitTypeId(udg_Aura_TrigUnit) == 0 then)
- You have indentation errors in your JASS code, also stylistically I suggest spreading out logical blocks a bit more to make the code more readable
- There's a lot of obscure numbers for the event triggers and they're not exactly clear
- Your recycling method is odd, why cleanup every aura at once instead of de-allocating each one as necessary? It just seems really messy and well bad frankly
- Your recycle also is leaking many groups (tempGroup needs to be nulled every time before you use CreateGroup() again, not just at the end as groups are agents
- Also your last SourceGroup is never destroyed whenever you run the cleanup, while the number of these you "leak" never goes up, there's no need to be leaking any at all and I can't see any reason to not also clean that one up

For those reasons I'm going to set this to needs fix, I hope you have the time to fix up the system as it's quite a neat idea generally
The system appears otherwise sound from the things mentioned above though I'll obviously need to go through it again after changes have been made, oh thought I'd mention you left the WIP part of your description accidentally XD

I was cleaning them all at once mainly because I wanted to avoid having Bribe's Indexer as a requirement :S

But This cannot work for ressurection properly unless I use Bribe's indexer, so there's nowhere to run to, unfortunately.

Also, I was working on this before so the version I have is qutie different from this one here, I'll get to work on it again when I can spare some time. I'll just get rid of all the groups and make an actual recycle method.
I was trying to make as much GUI as possible so GUI users could understand what was going on in the system, but that ended up creating some messy code, sorry xD
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
How can such a system, with many unfixed leaks, have 900+ downloads 😳
The only leaks I found are in the "Command" triggers which occur on chat events. The ones associated with the actual aura example & system do not appear to leak anywhere.

So the system doesn't seem to be leaking; rather only the stuff that people wouldn't actually copy into their map is leaking. Hence I don't see a problem.
 
Level 12
Joined
Feb 27, 2019
Messages
399
The only leaks I found are in the "Command" triggers which occur on chat events. The ones associated with the actual aura example & system do not appear to leak anywhere.

So the system doesn't seem to be leaking; rather only the stuff that people wouldn't actually copy into their map is leaking. Hence I don't see a problem.
U sure ?

Tank-Commander reported, at a date superior to last map version:
  • You have a group leak in your initialization (leaks 16 times).
  • Your recycle also is leaking many groups (tempGroup needs to be nulled every time before you use CreateGroup() again, not just at the end as groups are agents.
  • Also your last SourceGroup is never destroyed whenever you run the cleanup, while the number of these you "leak" never goes up, there's no need to be leaking any at all and I can't see any reason to not also clean that one up.

Or maybe are those not leaking anymore in recent W3 versions ?
  • Units owned by player (GUI) / GetUnitsOfPlayerAll (Jass).
  • Not nullifying the group variable after calling "DestroyGroup", as groups are agents.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
1) the Init trigger doesn't matter as much. It is just part of the demo.
2) >
  • Your recycle also is leaking many groups (tempGroup needs to be nulled every time before you use CreateGroup() again, not just at the end as groups are agents.
That statement is false. If the local variable is declared at the top of the whole trigger (which it is) then it only needs to be nulled at the bottom (which it is), unless there was a "return" statement somewhere that skipped it).

3) that may be, and is a fair point.
 
Level 12
Joined
Feb 27, 2019
Messages
399
1) the Init trigger doesn't matter as much. It is just part of the demo.
2) >
  • Your recycle also is leaking many groups (tempGroup needs to be nulled every time before you use CreateGroup() again, not just at the end as groups are agents.
That statement is false. If the local variable is declared at the top of the whole trigger (which it is) then it only needs to be nulled at the bottom (which it is), unless there was a "return" statement somewhere that skipped it).

3) that may be, and is a fair point.

About 3) "Your last SourceGroup is never destroyed whenever you run the cleanup":

After reading the code I'm not fully understanding why the last group is not removed ? Indeed in AA3M Clean SourceGroups he runs a loop from 0 to Aura_Number, and inside this loop he calls DestroyGroup(udg_Aura_SourceGroup[<index>]). Did you figure out why Tank-Commander said it was leaking ?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
About 3) "Your last SourceGroup is never destroyed whenever you run the cleanup":

After reading the code I'm not fully understanding why the last group is not removed ? Indeed in AA3M Clean SourceGroups he runs a loop from 0 to Aura_Number, and inside this loop he calls DestroyGroup(udg_Aura_SourceGroup[<index>]). Did you figure out why Tank-Commander said it was leaking ?
Well I said ambiguously that it "may be" the case, not that it for sure was. If you think it isn't leaking, then you might be right. But I haven't studied it well enough to determine an outcome.
 
Top