1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. The contestants were to create water structures for the 20th Terraining Contest. Choose one in the public poll!
    Dismiss Notice
  3. Join other hivers in a friendly concept-art contest. The contestants have to create a genie coming out of its container. We wish you the best of luck!
    Dismiss Notice
  4. The Melee Mapping Contest #4: 2v2 - Results are out! Step by to congratulate the winners!
    Dismiss Notice
  5. We're hosting the 15th Mini-Mapping Contest with YouTuber Abelhawk! The contestants are to create a custom map that uses the hidden content within Warcraft 3 or is inspired by any of the many secrets within the game.
    Dismiss Notice
  6. Check out the Staff job openings thread.
    Dismiss Notice

TorrentArray v1.1b

Submitted by AGD
This bundle is marked as approved. It works and satisfies the submission rules.
Torrent Array v1.1b


DESCRIPTION:

Torrent Array is a spell template that allows you to create many different spell variants, may it be
torrent-related spells or not. The thing that makes this different from a normal spell is that you can
create many spell variations out it without having to copy-paste the whole spell code and then
change the configuration. I can't explain it all here but all you need to know can be found in the
documentation. Another notable feature is the possibility to create different torrent array shapes
(See the images below). With the right configuration, you can create a circular or even a spiral
array of torrents.


HISTORY:

This resource started as a spell named "Torrents". Later on, due to constant updates and changes
in the spell's design, I found a way to allow users to have more than 1 set of configuration and
create many spell variants, while all are sharing a single spell mechanics.
And so, it is now a spell template. It now also has a better algorithm brought forth by the new
TorrentSystem included in the bundle. The resource also comes with three premade spell
configurations namely "Geysers", "Meteor Shower", and "Eruption Helix" to give users an idea of
how to make their own spell variety.


DEPENDENCIES:

Required:
TorrentSystem
SpellEvent
UniqueList
Table

Optional:
ResourcePreloader
WorldBounds


Screenshots

Torrent Array spell variants


Geysers
Spell Description
[​IMG]

Linear Geysers
[​IMG]

Circular Geysers
[​IMG]

Spiral Geysers
[​IMG]


Meteor Shower
Spell Description
[​IMG]


[​IMG]
[​IMG]
[​IMG]
[​IMG]


Eruption Helix
Spell Description
[​IMG]


[​IMG]
[​IMG]




Changelogs

Torrent Array (New Resource Name)

v1.1b
- Changed the configuration system
- Configurations are no longer attached to arrays (normal struct members), but to a boolexpr that is then evaluated by a trigger. As a result, you can now have dynamic configurations through the use of functions that can take parameters - Just like what you would do with a usual spell configuration.
- Updated Dependencies (specifically TorrentSystem)
- Other changes

v1.0
- Rewrote the entire code of the last version of Torrents
- Now integrated with TorrentSystem
- Now allows you to create as many configuration sets as you can, all with different activation spell
- Many other significant changes


Torrents (Old Resource Name)

v1.3c
- Not uploaded

v1.3b
- Not uploaded

v1.3
- Added ResourcePreloader as an optional requirement
- Added WorldBounds as an optional requirement
- Added AutoFly as an optional requirement
- Added a new boolean TARGET_IS_CENTER to the configuration
- Adding and removing crowform is now done at target units enumeration instead of periodically when being tossed
- Optimized code
- Some other fixes and changes

v1.2c
- Not uploaded

v1.2b
- Fixed the bug in the previous version where the torrent model dont appear when DummyRecycler is used
- Removed some redundant target unit check
- Caster is now the one to damage the targets instead of the dummy
- Other changes

v1.2
- Added Table to the spell requirement
- Added 3 optional requirements namely TimerUtils, DummyRecycler, and SpellEffectEVent
- Changed the variable naming to fit that of the JPAG's naming convention
- Other changes

v1.1c
- Added a new feature that enables you to choose whether enemy players can see the torrent borders or not
- Added to the configuration the option whether to enable or disable the toss unit feature

v1.1b
- Used a safe method in adding/removing crowform ability to the units
- Made a separate function for filtering target units
- Other changes

v1.1
- Added strom crow form to the dummy's default ability
- Added documentations throughout the script
- Inlined the arithmetic format to that of JPAG's
- Nullified the local vars inside the if nest
- Moved HASH and TEMPGROUP below the configuration section and initialized them within the global block

v1.0b
- Some Fixes
- Some code restructuring

v1.0
- First Upload
Previews
Contents

TorrentArray v1.1b (Map)

Reviews
MyPad
Nitpicks A lesser amount of spell requirements would be favorable. Spell samples should be separated from the system. Notes: None (Mostly addressed) Status: Approved
  1. AGD

    AGD

    Joined:
    Mar 29, 2016
    Messages:
    396
    Resources:
    13
    Spells:
    7
    Tutorials:
    1
    JASS:
    5
    Resources:
    13
    If this gets approved, I will release the update for the spell I made months ago, with this system integrated to it. The new update for that spell is pretty ready. I recoded the entire spell and there's some twist in the design of the configuration that is very nice in my opinion ;).
    The mentioned spell is mow moved here.
     
    Last edited: Feb 7, 2017
  2. Aniki

    Aniki

    Joined:
    Nov 7, 2014
    Messages:
    517
    Resources:
    4
    Spells:
    1
    JASS:
    3
    Resources:
    4
    For some reason peasants get stuck in midair which seems to happen only when dead units/corpses are in the AOE of the spell as well.

    In my opinion the damage should be done when the explosion happens and on the landing/crashing (falling from a great height) instead of the damage over time.

    When DummyRecycler is disabled (because its optional) Torrent doesn't compile:
    Code (vJASS):

    static if LIBRARY_DummyRecycler then
        set dummy = GetRecycledDummyAnyAngle(.centerX, .centerY, 0)
        call DummyAddRecycleTimer(dummy, DUMMY_DURATION)
    else
        set dummy = CreateUnit(DUMMY_OWNER, DUMMY_ID, .centerX, .centerY, 0) // <-- undeclared variable DUMMY_ID
        call UnitApplyTimedLife(dummy, 'BTLF', DUMMY_DURATION)
    endif
     


    I don't know why you have all of these:
    Code (vJASS):

              */boolean selfFilter                      /*  Determines if the <caster> unit is allowed as target
              */
    boolean allyFilter                      /*  Determines if allies of the <caster> unit are allowed as targets
              */
    boolean structureFilter                 /*  Determines if structures are allowed as targets
              */
    boolean mechanicalFilter                /*  Determines if mechanical units are allowed as targets
              */
    boolean magicImmuneFilter               /*  Determines if magic immune units are allowed as targets
              */
    boolean etherealFilter                  /*  Determines if ethereal units are allowed as targets
              */
    boolean illusionFilter                  /*  Determines if illusions are allowed as targets
              */
    boolean deadFilter                      /*  Determines if dead units are allowed as targets


    instead of a taking a single function that receives Torrent.instance (as a global) and sets
    Torrent.target_allowed = UnitAlive(Torrent.instance.u) or/and etc;
    for example. The function can be called with
    ForForce
    .

    PS: all those optinal libraries make a big mess in terms of readability in my opinion
     
  3. AGD

    AGD

    Joined:
    Mar 29, 2016
    Messages:
    396
    Resources:
    13
    Spells:
    7
    Tutorials:
    1
    JASS:
    5
    Resources:
    13
    I think I've found the cause of this, I'm not sure though.

    I think I'll leave the damage on landing part to the users (They can use the custom callback handlers).

    Will fix this

    If I understood correctly, that would mean that I can only have 1 type of unit filters for all torrent instances. What I mean is that you can't make it so that Torrent(1) only targets allies while Torrent(2) only targets enemies.
     
  4. Aniki

    Aniki

    Joined:
    Nov 7, 2014
    Messages:
    517
    Resources:
    4
    Spells:
    1
    JASS:
    3
    Resources:
    4
    I was thinking of something like this:
    Code (vJASS):

    library TargetAllowedDemo initializer init

    struct TargetAllowed
        static force ta_force
        static thistype instance
        static unit target
        static boolean target_allowed
        boolexpr filter_func

        private static method onInit takes nothing returns nothing
            set ta_force = CreateForce()
            call ForceAddPlayer(ta_force, Player(15))
        endmethod

        static method create takes code filter_func returns thistype
            local thistype this = allocate()
            set this.filter_func = Filter(filter_func)
            return this
        endmethod

        method test takes unit u returns boolean
            if u == null then
                return false
            endif

            // call filter_func with TargetAllowed.instance and TargetAllowed.target as globals
            // the result is expected to be stored in TargetAllowed.target_allowed
            set instance = this
            set target = u
            call ForceEnumPlayers(ta_force, this.filter_func)
            return target_allowed
        endmethod
    endstruct

    globals
        TargetAllowed tauren_or_giant
        TargetAllowed undead_and_alive
        TargetAllowed ta_active
    endglobals

    function ta_tauren_or_giant takes nothing returns boolean
        local TargetAllowed ta = TargetAllowed.instance

        set ta.target_allowed = /*
            */
    IsUnitType(ta.target, UNIT_TYPE_GIANT) /*
            */
    or IsUnitType(ta.target, UNIT_TYPE_TAUREN)

        return false
    endfunction

    // Filter(function that_doesnt_return_boolean) seems to work although it might not =)
    function ta_undead_and_alive takes nothing returns nothing // boolean
        local TargetAllowed ta = TargetAllowed.instance

        set ta.target_allowed = /*
            */
    IsUnitType(ta.target, UNIT_TYPE_UNDEAD) /*
            */
    and not IsUnitType(ta.target, UNIT_TYPE_DEAD)

        // return false
    endfunction

    function on_unit_selected takes nothing returns nothing
        local unit u = GetTriggerUnit()
        local string un = GetUnitName(u)

        if ta_active == tauren_or_giant then
            if ta_active.test(u) then
                call BJDebugMsg(un + " is a tauren or a giant")
            else
                call BJDebugMsg(un + " is not a tauren nor a giant")
            endif

        elseif ta_active == undead_and_alive then
            if ta_active.test(u) then
                call BJDebugMsg(un + " is an alive undead unit")
            else
                call BJDebugMsg(un + " is either dead or not an undead unit")
            endif
        endif

        set u = null
    endfunction

    private function init takes nothing returns nothing
        local trigger t

        set tauren_or_giant = TargetAllowed.create(function ta_tauren_or_giant)
        set undead_and_alive = TargetAllowed.create(function ta_undead_and_alive)
        set ta_active = tauren_or_giant

        set t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SELECTED)
        call TriggerAddAction(t, function on_unit_selected)
    endfunction

    endlibrary

     
     
  5. AGD

    AGD

    Joined:
    Mar 29, 2016
    Messages:
    396
    Resources:
    13
    Spells:
    7
    Tutorials:
    1
    JASS:
    5
    Resources:
    13
    I see, so that means the user will have to create different boolexprs functions for each torrent instances that he wish to have different unittype filters, right? That would be more hussle than just editing the boolean flags I guess.
    If only the FilteringSystem library by The Wrecker supports this kind of filtering, it would make life easier.

    EDIT:
    I think the cause of the tossed units getting stuck midair is that at some cases, the timer is prematurely paused. But I still need to confirm this.

    EDIT: Tested. Doesn't seem like it is the cause of the problem.
     
    Last edited: Jan 12, 2017
  6. Aniki

    Aniki

    Joined:
    Nov 7, 2014
    Messages:
    517
    Resources:
    4
    Spells:
    1
    JASS:
    3
    Resources:
    4

    I think I've found why peasants get stuck in midair, if you comment out/prevent from executing this function (in the map's header):
    Code (vJASS):

        private function A takes nothing returns nothing
            //local unit u = GetTriggerUnit()
            //call CreateUnit( GetOwningPlayer( u ), GetUnitTypeId( u ), GetRandomReal( I2R(WorldBounds.minX), I2R(WorldBounds.maxX) ), GetRandomReal( I2R(WorldBounds.minY), I2R(WorldBounds.maxY) ), GetRandomReal( 0, 360 ) )
            //call TriggerSleepAction( 10 )
            //call RemoveUnit( u )
            //set u = null
        endfunction
     

    then they don't get stuck anymore, i.e the problem wasn't with the spell.

    I think it has something to do with TSA and creating and killing units at the same time but I don't really know =).
     
  7. AGD

    AGD

    Joined:
    Mar 29, 2016
    Messages:
    396
    Resources:
    13
    Spells:
    7
    Tutorials:
    1
    JASS:
    5
    Resources:
    13
    I tested what you said and indeed the bug is gone. Alternatively, I also tried replacing the group swapping method with something like this instead
    Code (vJASS):
    call GroupAddGroup(g, tempGroup)
    loop
        set u = FirstOfGroup(tempGroup)
        exitwhen u == null
        call GroupRemoveUnit(tempGroup, u)
        //actions
    endloop
    and it also solves the bug. o_O

    EDIT:
    I now know exactly what's the problem =). It's because of the RemoveUnit(). Removed units aren't automatically removed from the group, they remain but they become
    null
    , thus, causing the loop to exit prematurely. Hence why Captain Griffen from wc3c made a GroupRefresh snippet.
     
    Last edited: Jan 13, 2017
  8. Aniki

    Aniki

    Joined:
    Nov 7, 2014
    Messages:
    517
    Resources:
    4
    Spells:
    1
    JASS:
    3
    Resources:
    4
    Right...
    FirstOfGroup
    returns null on removed (explicitly via RemoveUnit or implicitly via unit decay) units.

    Instead of using GroupRefresh (iterating the group and getting rid of removed units, before iterating the group with FirstOfGroup) you could also filter out dead units (corpses) so that they won't decay (get removed) while being tossed up and down.
    Or if you want to support tossing dead bodies up and down you can call
    UnitSuspendDecay(u, true)
    while doing so and
    UnitSuspendDecay(u, false)
    when done. Of course this would only work for implicitly removed units, i.e calling RemoveUnit on a dead unit would still be problematic.
     
  9. AGD

    AGD

    Joined:
    Mar 29, 2016
    Messages:
    396
    Resources:
    13
    Spells:
    7
    Tutorials:
    1
    JASS:
    5
    Resources:
    13
    UPDATED to v1.0b

    - Fixed the bug regarding tossed unit sbeing stuck midair
    - Changed some logical arrangements in code
    - Some additions
    - Many other changes
     
  10. AGD

    AGD

    Joined:
    Mar 29, 2016
    Messages:
    396
    Resources:
    13
    Spells:
    7
    Tutorials:
    1
    JASS:
    5
    Resources:
    13
    UPDATED

    - Merged the TorrentSystem and Torrents spell together in one bundle
    - Renamed the bundle to TorrentArray
    - Other changes listed on the main post
     
    Last edited: Feb 5, 2017
  11. KILLCIDE

    KILLCIDE

    Administrator

    Joined:
    Jul 22, 2015
    Messages:
    3,489
    Resources:
    20
    Models:
    2
    Icons:
    10
    Spells:
    7
    Tutorials:
    1
    Resources:
    20
    When I asked you to merge it in one bundle, I didn't mean to put them in the same map xP you could upload seperate maps, but still have them under one "bundle"
     
  12. AGD

    AGD

    Joined:
    Mar 29, 2016
    Messages:
    396
    Resources:
    13
    Spells:
    7
    Tutorials:
    1
    JASS:
    5
    Resources:
    13
    I guess I've leave it in one map, since TorrentArray requires TorrentSystem anyway so I see it pointless to have 2 maps when one of them contains all that is found on the two of them.
     
  13. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    6,107
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    This looks really cool.
     
  14. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    6,107
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    TorrentSystem and TorrentArray are both the main submission here? (It's not very clear to me because of the submission name and version numbers)
    I will only look at system and array at first.

    TorrentSystem:

    Why not applying a filter func in config instead of providing all specific bools? (or it can be instance specific, if needed)
    Though, the filters seem to cover most common cases by default already, but maybe the limitation is not needed.

    Code (vJASS):

              */method onTorrentExplode takes boolexpr expr returns nothing/*
                - Adds a boolexpr of the code that will run upon the Torrent's explosion

              */
    method onTorrentVanish takes boolexpr expr returns nothing/*
                - Adds a boolexpr of the code that will run upon the Torrent's disappearance, after tossed units are landed
                - This will not run when <tossUnits> is false

    ^From docu I don't very understand this. Does it instantly fire the mentioned event(s), or does it only register code to it?

    Code (vJASS):

                /* Check if this torrent tosses its targets
                   If yes, make sure it has finished its business
                   before destroying                                */

                if duration >= 2*TIMEOUT and .elapsed < duration then

    What is the functional meaning? If the condtion doesn't met, then it won't be deallocated in the destroy call? - but the dummy will be recycled?

    Code (vJASS):

                        loop
                            call DestroyEffect(LoadEffectHandle(table, this, count))
                            exitwhen count == 0
                            set count = count - 1
                        endloop

    It seems usually better if a exit loop condition is on very top, or is there a reason why it is not?

    set owner = GetOwningPlayer(caster)

    ^Seems it could be avoided when declaring owner as instance member.

    Why is there a usage of locals for attackty/damagetype and other members, if we already have access to the data with
    this.
    inside loop?

    Somehow I personaly don't very like such things like
    set table = TableArray[0x2000]
    , but yeh.. your preference weights more I believe.

    It's not really explained what a Torrent actually is. It starts right away with members, and functions to use.

    Sorry, I'm pretty on a rush, and may continue a other day with more feedback, and also for the ArrayTorrent.

    Edit:

    Suggestion to rename
    speed
    to
    speed_x
    or something alike.

    Torrent <->DummyUnit relation is 1:1, each torrent is associated by the unit. UnitIndex of the dummyunit could be used instead of allocation method.

    TorrentArray:

    Could you add a description of what the system exactly is?

    The API needs to explain the variable types next to the names.

    Maybe a list can be be required as external system, if you prefer.

    Why are all members doubled that a TorrentSystem already provides? Like Damage/Attacktype, etc. A torrent array, should only take usage of it, and can additionaly have new members, but at it's best it should not double anything.

    Code (vJASS):

    /* Implement map bounds */
                    static if LIBRARY_WorldBounds then
                        if centerX < WorldBounds.minX then
                            set centerX = WorldBounds.minX
                        elseif centerX > WorldBounds.maxX then
                            set centerX = WorldBounds.maxX
                        endif
                        if centerY < WorldBounds.minY then
                            set centerY = WorldBounds.minY
                        elseif centerY > WorldBounds.maxY then
                            set centerY = WorldBounds.maxY
                        endif
                    else
                        if centerX < minX then
                            set centerX = minX
                        elseif centerX > maxX then
                            set centerX = maxX
                        endif
                        if centerY < minY then
                            set centerY = minY
                        elseif centerY > maxY then
                            set centerY = maxY
                        endif
                    endif

    ^Such logics, only to get good x/y onCast. Maybe requring some libs is good for the code, or making an extra function to regulate the correct value. (
    x = normalize/regulate(x)
    )

    Why not stunning a unit instead of pause?
     
    Last edited: Oct 15, 2017
  15. AGD

    AGD

    Joined:
    Mar 29, 2016
    Messages:
    396
    Resources:
    13
    Spells:
    7
    Tutorials:
    1
    JASS:
    5
    Resources:
    13
    Yes they are both the submissions. TorrentSystem is a system that allows you to easily create uhm well... Torrents (sorry I just borrowed the term from a spell in DotA but I guess not everyone is familiar with it so I need to add a better description soon) while TorrentArray is a spell that summons Torrents in a fancy way (atleast for me =)) using the TorrentSystem. KILLCIDE suggested to put them in two different bundles under 1 resource thread but I find it awkward to do so since the bundle for TorrentArray would also contain TorrentSystem since it is its requirement which would make a separate bundle for TorrentSystem redundant. So yeah, it might be confusing, should I revert both their version numbers to 1 or what can you suggest?

    Btw, although I pretty much refer to TorrentArray as a spell, one can also argue or view it as a system because although it has a single core mechanics, it has a very 'open' style of configuration which allows you to configure many of its aspects (or even add to it using the callback functions, see the MeteorShower sample) compared to the usual configuration we often see, to the point where each configuration set that you make can already be considered as an individual spell itself (As KILLCIDE told me, it is a system that allows you to create many spell varieties) as you can see by testing the 2 sample configurations above.


    Indeed, will include them in the update.


    They register callback functions, onTorrentExplode() registers a code that will run when a torrent explodes (i.e., when explode() method is called internally) while onTorrentVanish() registers a code that will run when tossed units land.


    Yes, calling destroy should make the torrent instantly vanish/disappear for the user however, it should not be the case for its effects upon the tossed units because doing so would break the mechanics, that's why the system waits for the all the units to land and leaves the deallocation part to the periodic method later instead.


    It is because the loops need to run <number of borders> + 1 times since I put the model of the Torrent itself in the same hashtable with 0 as its key. If I will move it to the top the condition must be == -1 instead of 0.


    Well owner isn't declared as instance member, only caster or did you mean it's better to make owner an instance member instead?


    Ah right, this one. It is done when I was still addicted of micro-optimizations =), I stored them in locals so that the loop will not have to read arrays (instance members) repeatedly since the loop will run > 1 times on average (since the loop is a unitgroup iteration, it could possibly run many times depending on the aoe). But right now, yeah I think it would be cleaner and shorter if I haven't done those plus I don't think it would really tax on performance that much so I could let those locals go =).


    Maybe zSpeed because it is along z (height) axis


    Nice catch, will do next update.


    Will do


    I'll try to use Nes's lists


    It seems doubled but it actually is not because 1 torrentarray contains 1 or more torrents but the user only have access to the torrentarray members and not the individual composing torrent's members, which means that the individual torrent's members should be based/copied from the torrentarray, not the torrentarray basing its data from the torrents.
    It's like:
    Code (Text):
    //config
    torrentarray.data1 = <set by user>
    torrentarray.data2 = <set by user>
    //...

    //internal (loop through all torrents)
    torrent1.data1 = torrentarray.data1
    torrent1.data2 = torrentarray.data2
    //...

    torrent2.data1 = torrentarray.data1
    torrent2.data2 = torrentarray.data2
    //...

    torrentN.data1 = torrentarray.data1
    torrentN.data2 = torrentarray.data2
    //...

    Hmm, if I'd make it a separate function, It would still be of the same length because I only use them once in each lib.


    Right, pause might not be so good as it would have some unwanted side-effects, but I prefer if there would not be a stun special effect attached overhead the units =). How about setting both propwindow and turnrate to 0.00? I'm not so sure how exactly it mimics stun, I imagine they can still use abilities. But if there are no other alternative, then I'll use the stun.
     
  16. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    6,107
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    I personaly would maybe also tend to do TorrentSystem submission, and then TorrentArray as new submission, as TorrentSystem > TorrentArray. That fact alone that TorrentArray would anyways include TorrentSystem wouldn't bother me too much, as it's just like a normal requirement.

    Could we maybe rename it to registerOnTorrentExplode or so? I mean I have read the texts actually... but onTorrentExplode somehow sounds like some event to me as itself.
    Ah ok, I didn't reaylize it.^^ Maybe yes.
    But so there's no hard destroy? Like it instantly finished everything. Sorry maybe it's no too clever question, I dont have all scenarios in mind atm, if it makes sense for you not to allow a instant destroy then it maybe makes sense.

    Yeh it only tries to disable movement. Maybe a stun system is good, I'm currently not sure which is the 'best'.. though.
     
  17. AGD

    AGD

    Joined:
    Mar 29, 2016
    Messages:
    396
    Resources:
    13
    Spells:
    7
    Tutorials:
    1
    JASS:
    5
    Resources:
    13
    You mean separate submissions, or bundle?


    Right, I also find some of my old namings a bit off, will change it.


    Hmm, I'm actually thinking of one way to destroy the effects completely and not break the mechanics, that is, to drop all tossed units instantly.
     
  18. AGD

    AGD

    Joined:
    Mar 29, 2016
    Messages:
    396
    Resources:
    13
    Spells:
    7
    Tutorials:
    1
    JASS:
    5
    Resources:
    13
    Updated

    - The configuration now mimics the common convention of spell configurations (constant globals for static configurations and constant functions that take arguments for dynamic configurations)

    Torrent System is now made as a separate resource from this one.
     
    Last edited: May 2, 2018
  19. MyPad

    MyPad

    Spell Reviewer

    Joined:
    May 9, 2014
    Messages:
    1,244
    Resources:
    6
    Models:
    1
    Icons:
    1
    Spells:
    3
    JASS:
    1
    Resources:
    6

    Nitpicks


    • A lesser amount of spell requirements would be favorable.
    • Spell samples should be separated from the system.

    Notes:


    • None (Mostly addressed)

    Status:



    Approved