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

[Solved] Aegis Power

Status
Not open for further replies.
Level 24
Joined
May 15, 2013
Messages
3,782
Hello Hivers,

This is my request link of the ability - Aegis Power and Grand Smite
Now I tried making the ability Aegis Power, in GUI and JASS.
Each with their own problems.

A little overview:

Aegis Power - Releases an aura that causes nearby enemies to forcibly attack the caster. He then gains a temporary bonus armor (5/10/15). Lasts 8 seconds.
If Stunning Might is active, he will gain a temporary bonus in attack speed and movement speed (20/25/30%) and doubles the duration (8x2=16).

I have the main ability which will be used for the cast, Aegis Power (based from Taunt)
Then I made a dummy, with its dummy ability, Aegis Power (that gives armor, based from Faerie Fire, reversed effects)
Then another dummy ability, same name, but its effects increases Attack Speed and Movement Speed (based from Slow, reversed effects)
Another dummy ability, it is the same as the first dummy ability, that adds armor, but with doubled duration.
And Stunning Might is the ability that gives the addon, finished by Killcide (check link above)
------------------------------------------------------------------
GUI


  • AP Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set AP_Ability = Aegis Power
      • Set AP_AbilityASMS = Aegis Power (MS & AS)
      • Set AP_AbilityDefense = Aegis Power (Armor Bonus)
      • Set AP_AbilityDefenseTwice = Aegis Power (Armor Bonus +)
      • Set AP_DummyUnit = AP Dummy
      • -------- --------
      • Set AP_PeriodicTimer = (1.00 / 32.00)
      • Trigger - Add to AP Loop <gen> the event (Time - Every AP_PeriodicTimer seconds of game time)
  • AP Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to AP_Ability
    • Actions
      • -------- --------
      • Set AP_TotalCount = (AP_TotalCount + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • AP_TotalCount Equal to 1
        • Then - Actions
          • Trigger - Turn on AP Loop <gen>
        • Else - Actions
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • AP_RecycledSize Equal to 0
        • Then - Actions
          • Set AP_MaxIndex = (AP_MaxIndex + 1)
          • Set AP_Spell_ID = AP_MaxIndex
        • Else - Actions
          • Set AP_RecycledSize = (AP_RecycledSize - 1)
          • Set AP_Spell_ID = AP_RecycledStack[AP_RecycledSize]
      • Set AP_NodeNext[AP_Spell_ID] = 0
      • Set AP_NodeNext[AP_NodePrev[0]] = AP_Spell_ID
      • Set AP_NodePrev[AP_Spell_ID] = AP_NodePrev[0]
      • Set AP_NodePrev[0] = AP_Spell_ID
      • -------- --------
      • Set AP_Caster[AP_Spell_ID] = (Triggering unit)
      • Set AP_Owner[AP_Spell_ID] = (Triggering player)
      • Set AP_AbilityLvl[AP_Spell_ID] = (Level of AP_Ability for AP_Caster[AP_Spell_ID])
  • AP Loop
    • Events
    • Conditions
    • Actions
      • Set AP_Spell_ID = 0
      • For each (Integer AP_Looper) from 1 to AP_TotalCount, do (Actions)
        • Loop - Actions
          • Set AP_Spell_ID = AP_NodeNext[AP_Spell_ID]
          • -------- Checks if there is buff --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (AP_Caster[AP_Spell_ID] is in SM_CasterGroup) Equal to True
            • Then - Actions
              • Set AP_TempLoc = (Position of AP_Caster[AP_Spell_ID])
              • Unit - Create 1 AP_DummyUnit for Neutral Passive at AP_TempLoc facing Default building facing degrees
              • Set AP_Dummy[AP_Spell_ID] = (Last created unit)
              • Unit - Add AP_AbilityDefenseTwice to AP_Dummy[AP_Spell_ID]
              • Unit - Create 1 AP_DummyUnit for Neutral Passive at AP_TempLoc facing Default building facing degrees
              • Set AP_DummyMSAS[AP_Spell_ID] = (Last created unit)
              • Unit - Add AP_AbilityASMS to AP_DummyMSAS[AP_Spell_ID]
              • Unit - Set level of AP_AbilityDefenseTwice for AP_Dummy[AP_Spell_ID] to AP_AbilityLvl[AP_Spell_ID]
              • Unit - Set level of AP_AbilityASMS for AP_DummyMSAS[AP_Spell_ID] to AP_AbilityLvl[AP_Spell_ID]
              • Custom script: call RemoveLocation(udg_AP_TempLoc)
              • -------- --------
              • Unit - Order AP_Dummy[AP_Spell_ID] to Night Elf Druid Of The Talon - Faerie Fire AP_Caster[AP_Spell_ID]
              • Unit - Order AP_DummyMSAS[AP_Spell_ID] to Human Sorceress - Slow AP_Caster[AP_Spell_ID]
              • Unit - Remove Slow buff from AP_Caster[AP_Spell_ID]
              • Wait 0.25 seconds
              • Custom script: call RemoveUnit(udg_AP_Dummy[udg_Spell_ID])
              • Custom script: call RemoveUnit(udg_AP_DummyMSAS[udg_Spell_ID])
              • -------- --------
              • Set AP_RecycledStack[AP_RecycledSize] = AP_Spell_ID
              • Set AP_RecycledSize = (AP_RecycledSize + 1)
              • Set AP_NodeNext[AP_NodePrev[AP_Spell_ID]] = AP_NodeNext[AP_Spell_ID]
              • Set AP_NodePrev[AP_NodeNext[AP_Spell_ID]] = AP_NodePrev[AP_Spell_ID]
              • -------- --------
              • Set AP_TotalCount = (AP_TotalCount - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • AP_TotalCount Equal to 0
                • Then - Actions
                  • Trigger - Turn off AP Loop <gen>
                • Else - Actions
            • Else - Actions
              • Set AP_TempLoc = (Position of AP_Caster[AP_Spell_ID])
              • Unit - Create 1 AP_DummyUnit for Neutral Passive at AP_TempLoc facing Default building facing degrees
              • Set AP_Dummy[AP_Spell_ID] = (Last created unit)
              • Unit - Add AP_AbilityDefense to AP_Dummy[AP_Spell_ID]
              • Unit - Set level of AP_AbilityDefense for AP_Dummy[AP_Spell_ID] to AP_AbilityLvl[AP_Spell_ID]
              • Custom script: call RemoveLocation(udg_AP_TempLoc)
              • -------- --------
              • Unit - Order AP_Dummy[AP_Spell_ID] to Night Elf Druid Of The Talon - Faerie Fire AP_Caster[AP_Spell_ID]
              • Wait 0.25 seconds
              • Custom script: call RemoveUnit(udg_AP_Dummy[udg_Spell_ID])
              • -------- --------
              • Set AP_RecycledStack[AP_RecycledSize] = AP_Spell_ID
              • Set AP_RecycledSize = (AP_RecycledSize + 1)
              • Set AP_NodeNext[AP_NodePrev[AP_Spell_ID]] = AP_NodeNext[AP_Spell_ID]
              • Set AP_NodePrev[AP_NodeNext[AP_Spell_ID]] = AP_NodePrev[AP_Spell_ID]
              • -------- --------
              • Set AP_TotalCount = (AP_TotalCount - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • AP_TotalCount Equal to 0
                • Then - Actions
                  • Trigger - Turn off AP Loop <gen>
                • Else - Actions


All seems good at first cast, it works, but on the next, it doesn't, then so on. It appears the
ability may not loop, and I have no idea where or what part it is found.
The loop was based from Killcide's Shield Rush, (which I requested and he finished, found on the link) but I don't really get the Node parts.

------------------------------------------------------------------
JASS


JASS:
library AegisPower initializer Init

function True takes nothing returns boolean
    return true
endfunction

function Cons takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == udg_AP_Ability ) ) then
        return false
    endif
    return true
endfunction

function AegisPower takes nothing returns nothing
    local unit a
    local unit b
    if (IsUnitInGroup(GetTriggerUnit(), udg_SM_CasterGroup)) == true
        call CreateUnitAtLoc(GetTriggerPlayer(), 'h001', GetUnitLoc(GetTriggerUnit), 0.00)
        set unit a = GetLastCreatedUnit()
        call UnitAddAbility(a, udg_AP_AbilityDefenseTwice)
        call CreateUnitAtLoc(GetTriggerPlayer(), 'h001', GetUnitLoc(GetTriggerUnit), 0.00)
        set unit b = GetLastCreatedUnit()
        call UnitAddAbility(a, udg_AP_AbilityASMS)
        call IssueTargetOrder(a, "faeriefire", GetTriggerUnit())
        call IssueTargetOrder(b, "slow", GetTriggerUnit())
        call RemoveUnit(a)
        call RemoveUnit(b)
    elseif
        call CreateUnitAtLoc(GetTriggerPlayer(), 'h001', GetUnitLoc(GetTriggerUnit), 0.00)
        set unit a = GetLastCreatedUnit()
        call UnitAddAbility(a, udg_AP_AbilityDefense)
        call IssueTargetOrder(a, "faeriefire", GetTriggerUnit())
        call RemoveUnit(a)
    endif
    
    set unit a = null
    set unit b = null
    
endfunction

//===========================================================================
function Init takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    local integer i = 0
    loop
        exitwhen i > 15
            call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, Filter(function True))
            set i = i + 1
    endloop
    call TriggerAddCondition( t, Filter( function Cons ) )
    call TriggerAddAction( t, function AegisPower )
endfunction


In Jass, I did a look on some tutorials, and wroted this, actually I prefer GUI since I have no frickin idea why my Warcraft won't run when I test it with this.
Come to think of it, everything that I wrote in Jass don't work, even the ones I just edited (must be my WE or JassNewGenWE)

==================================

Well, I really suck at abilities and spellmaking, so please, help me out :)
 

Ardenian

A

Ardenian

As for the Jass version, you do library AegisPower initializer Init but you never do endlibrary.
I am not very experienced with vJass, but I think that's how it works.
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
Libraries are for vJASS, not JASS. If you're coding your spell in JASS, you only need regular functions.

The loop was based from Killcide's Shield Rush, (which I requested and he finished, found on the link) but I don't really get the Node parts.
I use a data structure called linked list to make my spells MUI. They are a bit confusing to understand at first, especially if you've never been exposed to them before. I suggest looking into dynamic indexing.
 
Level 24
Joined
May 15, 2013
Messages
3,782
I'm getting to understand this GUI method, though I'm not sure where the problem for this current spell will be.

As for the JASS part, I ended up the map not playing, either the WE or newgenWE is old, or I just screw up the functions. Either way, I'll stick to GUI for now.

EDIT: Yes, it works now, tested it, I like it. I'm not sure though if it might leak, if anyone notices something wrong with it, just tell me.
Other than that, thank you so much guys, this will help me in future spellmaking. :D


  • AP Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set AP_Ability = Aegis Power
      • Set AP_AbilityASMS = Aegis Power (MS & AS)
      • Set AP_AbilityDefense = Aegis Power (Armor Bonus)
      • Set AP_AbilityDefenseTwice = Aegis Power (Armor Bonus +)
      • Set AP_DummyUnit = AP Dummy
      • -------- --------
      • Set AP_PeriodicTimer = (1.00 / 32.00)
      • Trigger - Add to AP Loop <gen> the event (Time - Every AP_PeriodicTimer seconds of game time)
  • AP Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to AP_Ability
    • Actions
      • -------- --------
      • Set AP_Index = (AP_Index + 1)
      • Set AP_Caster[AP_Index] = (Triggering unit)
      • Set AP_Owner[AP_Index] = (Triggering player)
      • Set AP_AbilityLvl[AP_Index] = (Level of AP_Ability for AP_Caster[AP_Index])
      • Set AP_SMLvl[AP_Index] = (Level of SM_Ability for AP_Caster[AP_Index])
      • Set AP_Counter[AP_Index] = 0
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • AP_Index Equal to 1
        • Then - Actions
          • Trigger - Turn on AP Loop <gen>
        • Else - Actions
  • AP Loop
    • Events
    • Conditions
    • Actions
      • For each (Integer AP_Looper) from 1 to AP_Index, do (Actions)
        • Loop - Actions
          • -------- Checks if there is buff --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (AP_Caster[AP_Looper] is in SM_CasterGroup) Equal to True
            • Then - Actions
              • Set AP_TempLoc = (Position of AP_Caster[AP_Looper])
              • Unit - Create 1 AP_DummyUnit for Neutral Passive at AP_TempLoc facing Default building facing degrees
              • Set AP_Dummy[AP_Looper] = (Last created unit)
              • Unit - Add AP_AbilityDefenseTwice to AP_Dummy[AP_Looper]
              • Unit - Add a 0.25 second Generic expiration timer to AP_Dummy[AP_Looper]
              • Unit - Create 1 AP_DummyUnit for Neutral Passive at AP_TempLoc facing Default building facing degrees
              • Set AP_DummyMSAS[AP_Looper] = (Last created unit)
              • Unit - Add AP_AbilityASMS to AP_DummyMSAS[AP_Looper]
              • Unit - Add a 0.25 second Generic expiration timer to AP_DummyMSAS[AP_Looper]
              • Unit - Set level of AP_AbilityDefenseTwice for AP_Dummy[AP_Looper] to AP_AbilityLvl[AP_Looper]
              • Unit - Set level of AP_AbilityASMS for AP_DummyMSAS[AP_Looper] to AP_SMLvl[AP_Looper]
              • Custom script: call RemoveLocation(udg_AP_TempLoc)
              • -------- --------
              • Unit - Order AP_Dummy[AP_Looper] to Night Elf Druid Of The Talon - Faerie Fire AP_Caster[AP_Looper]
              • Unit - Order AP_DummyMSAS[AP_Looper] to Human Sorceress - Slow AP_Caster[AP_Looper]
              • -------- --------
              • -------- Takes away the Stunning Might Buff --------
              • -------- --------
              • Unit - Remove SM_Buff buff from AP_Caster[AP_Looper]
              • Unit Group - Remove AP_Caster[AP_Looper] from SM_CasterGroup
              • Special Effect - Destroy (Load 3 of SM_Unit_ID in SM_Hash)
              • -------- --------
              • Set AP_Counter[AP_Looper] = (AP_Counter[AP_Looper] + 1)
              • -------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • AP_Counter[AP_Looper] Greater than or equal to 1
                • Then - Actions
                  • Set AP_Caster[AP_Looper] = AP_Caster[AP_Index]
                  • Set AP_Owner[AP_Looper] = AP_Owner[AP_Index]
                  • Set AP_Counter[AP_Looper] = AP_Counter[AP_Index]
                  • Set AP_AbilityLvl[AP_Looper] = AP_AbilityLvl[AP_Index]
                  • Set AP_SMLvl[AP_Looper] = AP_SMLvl[AP_Index]
                  • Set AP_Index = (AP_Index - 1)
                  • Set AP_Looper = (AP_Looper - 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • AP_Index Equal to 0
                    • Then - Actions
                      • Trigger - Turn off AP Loop <gen>
                    • Else - Actions
                • Else - Actions
            • Else - Actions
              • Set AP_TempLoc = (Position of AP_Caster[AP_Looper])
              • Unit - Create 1 AP_DummyUnit for Neutral Passive at AP_TempLoc facing Default building facing degrees
              • Set AP_Dummy[AP_Looper] = (Last created unit)
              • Unit - Add AP_AbilityDefense to AP_Dummy[AP_Looper]
              • Unit - Add a 0.25 second Generic expiration timer to AP_Dummy[AP_Looper]
              • Unit - Set level of AP_AbilityDefense for AP_Dummy[AP_Looper] to AP_AbilityLvl[AP_Looper]
              • Custom script: call RemoveLocation(udg_AP_TempLoc)
              • -------- --------
              • Unit - Order AP_Dummy[AP_Looper] to Night Elf Druid Of The Talon - Faerie Fire AP_Caster[AP_Looper]
              • -------- --------
              • Set AP_Counter[AP_Looper] = (AP_Counter[AP_Looper] + 1)
              • -------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • AP_Counter[AP_Looper] Greater than or equal to 1
                • Then - Actions
                  • Set AP_Caster[AP_Looper] = AP_Caster[AP_Index]
                  • Set AP_Owner[AP_Looper] = AP_Owner[AP_Index]
                  • Set AP_Counter[AP_Looper] = AP_Counter[AP_Index]
                  • Set AP_AbilityLvl[AP_Looper] = AP_AbilityLvl[AP_Index]
                  • Set AP_SMLvl[AP_Looper] = AP_SMLvl[AP_Index]
                  • Set AP_Index = (AP_Index - 1)
                  • Set AP_Looper = (AP_Looper - 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • AP_Index Equal to 0
                    • Then - Actions
                      • Trigger - Turn off AP Loop <gen>
                    • Else - Actions
                • Else - Actions
 
Last edited by a moderator:
Level 37
Joined
Jul 22, 2015
Messages
3,485
Out of curiousity, how often does the loop run? Are you constantly creating dummies and giving them the abilities every 0.03 seconds?

EDIT: After looking at both triggers, the only difference I see is that you changed the data structure and removed the wait timers. The linked list you had in the first set of triggers are correct, so I'm led to believe that maybe the wait timers were screwing up with the loop?
 
Last edited:
Level 24
Joined
May 15, 2013
Messages
3,782
Here, works as well.

  • AP Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set AP_Ability = Aegis Power
      • Set AP_AbilityASMS = Aegis Power (MS & AS)
      • Set AP_AbilityDefense = Aegis Power (Armor Bonus)
      • Set AP_AbilityDefenseTwice = Aegis Power (Armor Bonus +)
      • Set AP_DummyUnit = AP Dummy
      • -------- --------
      • Set AP_TempLoc = (Center of (Playable map area))
      • Unit - Create 1 AP_DummyUnit for Neutral Passive at AP_TempLoc facing Default building facing degrees
      • Set AP_DummyII = (Last created unit)
      • Unit - Add AP_AbilityDefense to AP_DummyII
      • Custom script: call RemoveUnit( udg_AP_DummyII )
      • Unit - Create 1 AP_DummyUnit for Neutral Passive at AP_TempLoc facing Default building facing degrees
      • Set AP_DummyIII = (Last created unit)
      • Unit - Add AP_AbilityDefenseTwice to AP_DummyIII
      • Custom script: call RemoveUnit( udg_AP_DummyIII )
      • Unit - Create 1 AP_DummyUnit for Neutral Passive at AP_TempLoc facing Default building facing degrees
      • Set AP_DummyIIII = (Last created unit)
      • Unit - Add AP_AbilityASMS to AP_DummyIII
      • Custom script: call RemoveUnit( udg_AP_DummyIIII )
      • Custom script: call RemoveLocation(udg_AP_TempLoc)
  • AP Cast II
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to AP_Ability
    • Actions
      • Set AP_CasterI = (Triggering unit)
      • Set AP_PlayerI = (Triggering player)
      • Set AP_AbilityLvlI = (Level of AP_Ability for AP_CasterI)
      • Set AP_SMLvlI = (Level of SM_Ability for AP_CasterI)
      • -------- xxx --------
      • Set AP_TempLoc = (Position of AP_CasterI)
      • -------- Check if caster has buff --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (AP_CasterI is in SM_CasterGroup) Equal to True
        • Then - Actions
          • Unit - Create 1 AP_DummyUnit for Neutral Passive at AP_TempLoc facing Default building facing degrees
          • Set AP_DummyIII = (Last created unit)
          • Unit - Add AP_AbilityDefenseTwice to AP_DummyIII
          • Unit - Add a 0.25 second Generic expiration timer to AP_DummyIII
          • Unit - Create 1 AP_DummyUnit for Neutral Passive at AP_TempLoc facing Default building facing degrees
          • Set AP_DummyIIII = (Last created unit)
          • Unit - Add AP_AbilityASMS to AP_DummyIIII
          • Unit - Add a 0.25 second Generic expiration timer to AP_DummyIIII
          • Unit - Set level of AP_AbilityDefenseTwice for AP_DummyIII to AP_AbilityLvlI
          • Unit - Set level of AP_AbilityASMS for AP_DummyIIII to AP_SMLvlI
          • -------- --------
          • Unit - Order AP_DummyIII to Night Elf Druid Of The Talon - Faerie Fire AP_CasterI
          • Unit - Order AP_DummyIIII to Human Sorceress - Slow AP_CasterI
          • -------- --------
          • -------- Takes away the Stunning Might Buff --------
          • -------- --------
          • Unit - Remove SM_Buff buff from AP_CasterI
          • Unit Group - Remove AP_CasterI from SM_CasterGroup
          • Special Effect - Destroy (Load 3 of SM_Unit_ID in SM_Hash)
        • Else - Actions
          • Unit - Create 1 AP_DummyUnit for Neutral Passive at AP_TempLoc facing Default building facing degrees
          • Set AP_DummyII = (Last created unit)
          • Unit - Add AP_AbilityDefense to AP_DummyII
          • Unit - Add a 0.25 second Generic expiration timer to AP_DummyII
          • Unit - Set level of AP_AbilityDefense for AP_DummyII to AP_AbilityLvlI
          • -------- --------
          • Unit - Order AP_DummyII to Night Elf Druid Of The Talon - Faerie Fire AP_CasterI
      • Custom script: call RemoveLocation(udg_AP_TempLoc)
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
  • You only have to preload the dummy unit and the abilities once on map init, so this will do:
    • Set AP_TempLoc = (Center of (Playable map area))
    • Unit - Create 1 AP_DummyUnit for Neutral Passive at AP_TempLoc facing Default building facing degrees
    • Set AP_DummyII = (Last created unit)
    • Unit - Add AP_AbilityDefense to AP_DummyII
    • Unit - Add AP_AbilityDefenseTwice to AP_DummyII
    • Unit - Add AP_AbilityASMS to AP_DummyII
    • Unit - Remove AP_DummyII
    • Custom script: call RemoveLocation(udg_AP_TempLoc)

  • What's the reason why you create two dummies to cast two different spells when you can just have one dummy cast both spells?
  • I see you loading an effect from the hashtable, but I don't see caching a value for SM_Unit_ID anywhere. You will be destroying whatever the most recent "SM_Unit_ID" was instead of the actual handle of the caster. Add this to your trigger:
    • Custom script: set udg_SM_Unit_ID = GetHandleId(udg_AP_Caster1)

There are other things I can nitpick about, but that's not what the thread is about xP other than that, everything looks good.
 
Status
Not open for further replies.
Top