1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Seek unity between the elements in the 22nd Terraining Contest Poll.
    Dismiss Notice
  3. Seize the moment! The 18th Mini Mapping Contest has commenced.
    Dismiss Notice
  4. Gather 'round - the 20th Icon Contest Poll is out.
    Dismiss Notice
  5. The heavens smile on the old faithful. The 16th Techtree Contest has begun.
    Dismiss Notice
  6. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Polarisation - v1.3

Submitted by Mr_Bean
This bundle is marked as approved. It works and satisfies the submission rules.

Polarisation - v1.3

By Mr_Bean



Introduction


I saw Sage Chow's post in a spell idea workshop and I liked it a lot, so I decided to code it. Full credits to Sage Chow for the awesome idea!

Spell Description



Polarisation

[​IMG]
Active: Runs an electric charge through all units in the targeted area, applying either a positive or negative charge to them.
If the target has no charge or a negative charge, a positive charge will be applied. If it has a positive charge, a negavite charge will be applied.
All negatively charged units will zap a nearby positively charged enemy unit periodically.
Charges last for 90 seconds.

Level 1: 50 zap damage
Level 2: 75 zap damage
Level 3: 100 zap damage

Cooldown: 10 seconds.

Requirements


For this spell you will simply need JASS NewGen Pack [LINK] and the latest version of JASSHelper [LINK].

Code


vJASS Code
Code (vJASS):
library Polarisation initializer onInit requires TimerUtils

    //**************************************************\\
    //*** START OF CONFIGURABLES                     ***\\
    //**************************************************\\
   
    globals
   
        // Raw ID of the "Polarisation" hero ability:
        private constant integer SPELL_ID           = 'A000'
       
        // Enable preloading to prevent in-game lag:
        private constant boolean ENABLE_PRELOAD     = true
        // How long the charge lasts on each unit:
        private constant real    DURATION           = 90.0
        // Area of effect of the spell:
        private constant real    SPELL_AOE          = 300.0
        // How often negative units zap positive units:
        private constant real    ZAP_FREQUENCY      = 1.0
        // How close a positive unit needs to be to a negative one to get zapped:
        private constant real    ZAP_AOE            = 500.0
        // How often the system updates each unit's remaining time (shouldn't need to be changed):
        private constant real    UPDATE_FREQUENCY   = 0.1
        // How long the lightning bolt lasts:
        private constant real    BOLT_DURATION      = 0.5
        // Code of the desired lightning:
        private constant string  BOLT_CODE          = "CLPB"
        // Effect created on charged untis:
        private constant string  EFFECT             = "Abilities\\Spells\\Orc\\Purge\\PurgeBuffTarget.mdl"
        // Attachment point of EFFECT:
        private constant string  EFFECT_ATTACHMENT  = "origin"
        // Effect created on units when they get zapped:
        private constant string  ZAP_EFFECT         = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
        // Attachment point for ZAP_EFFECT:
        private constant string  ZAP_EFFECT_ATTACH  = "origin"
        // Effect created at the target point:
        private constant string  AREA_EFFECT        = "war3mapImported\\RollingStormSFX.mdx"
        // Colour of the floating text showing a +:
        private constant string  POSITIVE_COLOUR    = "|cff00ff00"
        // Colour of the floating text showing a -:
        private constant string  NEGATIVE_COLOUR    = "|cffff0000"

    endglobals
   
    // Configure how the damage per level is calculated:
    private function GetDamage takes integer level returns real
        return (25.0 * level) + 25.0
    endfunction
   
    //**************************************************\\
    //*** ADVANCED CONFIGURABLES                     ***\\
    //**************************************************\\
   
    globals
   
        private constant real    LIGHTNING_UPDATE_FREQUENCY     = 0.03      // How often lightnings are updated.
        private constant real    TEXTTAG_UPDATE_FREQUENCY       = 0.03      // How often texttags are updated.
        private constant real    TEXTTAG_HEIGHT_OFFSET          = 25.0      // Height offset of texttags.
        private constant real    TEXTTAG_HEIGHT                 = 0.035     // Height of texttags when created.
       
        private constant string  POSITIVE = "positive"  // Name for positive charge.
        private constant string  NEGATIVE = "negative"  // Name for negative charge.
        private constant key     CHARGE_KEY             // The unit's current charge (positive/negative).
        private constant key     TIME_KEY               // How long the charge has left on the unit.
        private constant key     LEVEL_KEY              // The level of the spell cast on the unit.
        private constant key     TEXT_TAG_KEY           // The unit's texttag showing it's charge.
        private constant key     EFFECT_KEY             // The unit's effect.
        private constant key     CASTER_KEY             // Who cast the spell on the unit.
       
    endglobals
   
    //**************************************************\\
    //*** END OF CONFIGURABLES                       ***\\
    //**************************************************\\
   
    globals
   
        private hashtable ht = InitHashtable()  // Stores all the data.
        private group positive = CreateGroup()  // Stores all positive units.
        private group negative = CreateGroup()  // Stores all negative units.
        private group enumG = CreateGroup()     // For group enumeration.
        private unit dummy                      // Temporary unit for dummy casting.
        private unit enumU                      // For group enumeration.
        private timer textTagTimer              // Timer that moves all units' texttags.
        private timer updateTimer               // Timer that updates all units' time remaining.
        private timer zapTimer                  // Timer that makes negatives zap positives.
        private boolean isTicking = false       // Saves whether the timers are ticking or not.
       
    endglobals
   
    //**************************************************
   
    /*
        True if unit is:
            - alive
            - not magic immune
            - not a structure
    */

   
    private function IsUnitTargetable takes unit u returns boolean
        return not IsUnitType(u, UNIT_TYPE_DEAD) and not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(u, UNIT_TYPE_STRUCTURE)
    endfunction
   
   
   
    // Creates a texttag which is only visible to the specified player:
    private function NewTextTagUnitVis takes string colour, string text, unit u, player p returns texttag
        local texttag tt = CreateTextTag()
       
        call SetTextTagText(tt, colour + text + "|r", TEXTTAG_HEIGHT)
        call SetTextTagPosUnit(tt, u, TEXTTAG_HEIGHT_OFFSET)
        call SetTextTagPermanent(tt, true)
       
        if IsPlayerAlly(GetLocalPlayer(), p) then
            call SetTextTagVisibility(tt, true)
        endif
       
        return tt
    endfunction

    //**************************************************
   
    private struct Lightning
        unit u1
        unit u2
        unit caster // Used for dealing damage.
        lightning bolt
        real damage
        real left
       
        private method destroy takes nothing returns nothing
            call DestroyLightning(.bolt)
            set .bolt = null
            set .u1 = null
            set .u2 = null
            set .caster = null
            call .deallocate()
        endmethod
       
        private static method move takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
           
            // Move the lightning and update time left:
            call MoveLightning(.bolt, false, GetUnitX(.u1), GetUnitY(.u1), GetUnitX(.u2), GetUnitY(.u2))
            set .left = .left - LIGHTNING_UPDATE_FREQUENCY
           
            // If the time has expired, damage the target and create an effect:
            if .left <= 0 then
                call ReleaseTimer(GetExpiredTimer())
                call UnitDamageTarget(.caster, .u2, .damage, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
                call DestroyEffect(AddSpecialEffectTarget(ZAP_EFFECT, .u2, ZAP_EFFECT_ATTACH))
                call .destroy()
            endif
           
        endmethod
       
        public static method create takes unit u1, unit u2, unit c, real dmg returns thistype
            local thistype this = thistype.allocate()
           
            // Store stuff:
            set .u1 = u1
            set .u2 = u2
            set .caster = c
            set .damage = dmg
            set .left = BOLT_DURATION
           
            // Create lightning and start timer:
            set .bolt = AddLightning(BOLT_CODE, true, GetUnitX(.u1), GetUnitY(.u1), GetUnitX(.u2), GetUnitY(.u2))
            call TimerStart(NewTimerEx(this), LIGHTNING_UPDATE_FREQUENCY, true, function thistype.move)
           
            return this
        endmethod
   
    endstruct
   
    private function MoveTextTag takes nothing returns nothing
        // Move the texttag to the unit:
        call SetTextTagPosUnit(LoadTextTagHandle(ht, GetHandleId(GetEnumUnit()), TEXT_TAG_KEY), GetEnumUnit(), TEXTTAG_HEIGHT_OFFSET)
    endfunction
   
    private function DisplayCharge takes nothing returns nothing
        // If there are no units in either group, pause all timers:
        if CountUnitsInGroup(positive) == 0 and CountUnitsInGroup(negative) == 0 then
       
            set isTicking = false
            call PauseTimer(textTagTimer)
            call PauseTimer(updateTimer)
            call PauseTimer(zapTimer)
       
        // Otherwise, move all the units' texttags:
        else
            call ForGroup(positive, function MoveTextTag)
            call ForGroup(negative, function MoveTextTag)
        endif
       
    endfunction
   
    private function ZapPositivesEnum takes nothing returns nothing
        local unit u = GetEnumUnit()
        local unit temp
        local boolean stop = false
       
        // Group all unit near the target:
        call GroupEnumUnitsInRange(enumG, GetUnitX(u), GetUnitY(u), ZAP_AOE, null)
       
        loop
            set temp = GroupPickRandomUnit(enumG) // Pick a random unit.
            exitwhen temp == null or stop // Stop searching if the unit is alive and positive.
           
            if not IsUnitType(temp, UNIT_TYPE_DEAD) and LoadStr(ht, GetHandleId(temp), CHARGE_KEY) == POSITIVE then
                set stop = true
                call Lightning.create(u, temp, LoadUnitHandle(ht, GetHandleId(temp), CASTER_KEY), GetDamage(LoadInteger(ht, GetHandleId(temp), LEVEL_KEY))) // Create a lightning (also damages).
            endif
           
            call GroupRemoveUnit(enumG, temp)
           
        endloop
       
        call GroupClear(enumG)
        set u = null
        set temp = null
    endfunction
   
    private function ZapPositives takes nothing returns nothing
        // For all positive units, zap nearby negatives:
        call ForGroup(negative, function ZapPositivesEnum)
    endfunction
   
    private function CheckDuration takes nothing returns nothing
        local unit u = GetEnumUnit()
        local integer handleId = GetHandleId(u)
        local real time = LoadReal(ht, handleId, TIME_KEY)
        local string status = LoadStr(ht, handleId, CHARGE_KEY)
       
        set time = time - UPDATE_FREQUENCY
       
        // If the unit's charge expires or it is dead:
        if time <= 0 or IsUnitType(u, UNIT_TYPE_DEAD) then
           
            // Remove from groups:
            if status == POSITIVE then
                call GroupRemoveUnit(positive, u)
            else
                call GroupRemoveUnit(negative, u)
            endif
           
            call DestroyTextTag(LoadTextTagHandle(ht, handleId, TEXT_TAG_KEY)) // Destroy texttag.
            call DestroyEffect(LoadEffectHandle(ht, handleId, EFFECT_KEY)) // Destroy effect.
            call FlushChildHashtable(ht, handleId) // Flush hashtable.
       
        // Otherwise, update it's time left:
        else
            call SaveReal(ht, handleId, TIME_KEY, time)
        endif
       
        set u = null
    endfunction
   
    private function CheckGroups takes nothing returns nothing
        // For positives and negatives, check their remaining durations and whether each unit is alive:
        call ForGroup(positive, function CheckDuration)
        call ForGroup(negative, function CheckDuration)
    endfunction
   
    private function RegisterUnit takes unit u, unit c, integer level, player p returns nothing
        local integer handleId = GetHandleId(u)
        local string status = LoadStr(ht, handleId, CHARGE_KEY)
        local texttag tt = LoadTextTagHandle(ht, handleId, TEXT_TAG_KEY)
        local effect eff = LoadEffectHandle(ht, handleId, EFFECT_KEY)
       
        // If the unit already has a texttag, destroy it:
        if tt != null then
            call DestroyTextTag(tt)
            set tt = null
        endif
       
        // If the unit already has an effect, destroy it:
        if eff != null then
            call DestroyEffect(eff)
            set eff = null
        endif
       
        call SaveReal(ht, handleId, TIME_KEY, DURATION) // Save duration.
        call SaveInteger(ht, handleId, LEVEL_KEY, level) // Save ability level.
        call SaveEffectHandle(ht, handleId, EFFECT_KEY, AddSpecialEffectTarget(EFFECT, u, EFFECT_ATTACHMENT)) // Create and save effect.
        call SaveUnitHandle(ht, handleId, CASTER_KEY, c) // Save caster (for dealing damage).
       
        // If the unit has a positive charge:
        if status == POSITIVE then
       
            call SaveStr(ht, handleId, CHARGE_KEY, NEGATIVE) // Change it to negative.
            call GroupRemoveUnit(positive, u) // Remove from positives.
            call GroupAddUnit(negative, u) // Add to negatives.
            call SaveTextTagHandle(ht, handleId, TEXT_TAG_KEY, NewTextTagUnitVis(NEGATIVE_COLOUR, "-", u, p)) // Create a texttag and save it.
           
        // Otherwise:
        else
       
            call SaveStr(ht, handleId, CHARGE_KEY, POSITIVE) // Change it to positive.
           
            if IsUnitInGroup(u, negative) then // Remove from negatives if it is in the group.
                call GroupRemoveUnit(negative, u)
            endif
           
            call GroupAddUnit(positive, u) // Add to positives.
            call SaveTextTagHandle(ht, handleId, TEXT_TAG_KEY, NewTextTagUnitVis(POSITIVE_COLOUR, "+", u, p)) // Create a texttag and save it.
           
        endif
       
    endfunction
   
    private function SpellActions takes nothing returns nothing
        local unit caster = GetTriggerUnit()
        local player owner = GetTriggerPlayer()
        local integer level = GetUnitAbilityLevel(caster, SPELL_ID)
       
        call DestroyEffect(AddSpecialEffect(AREA_EFFECT, GetSpellTargetX(), GetSpellTargetY()))
        // Group all units within range of the point:
        call GroupEnumUnitsInRange(enumG, GetSpellTargetX(), GetSpellTargetY(), SPELL_AOE, null)
       
        for enumU in enumG
       
            if not IsUnitType(enumU, UNIT_TYPE_DEAD) and IsUnitTargetable(enumU) then
           
                // Register the target in the 'system':
                call RegisterUnit(enumU, caster, level, owner)
               
                // Start the timers if they aren't already going:
                if not isTicking then
               
                    set isTicking = true
                    call TimerStart(textTagTimer, TEXTTAG_UPDATE_FREQUENCY, true, function DisplayCharge)
                    call TimerStart(updateTimer, UPDATE_FREQUENCY, true, function CheckGroups)
                    call TimerStart(zapTimer, ZAP_FREQUENCY, true, function ZapPositives)
                   
                endif
               
            endif
       
        endfor
       
        set caster = null
        set owner = null
    endfunction
   
    private function CheckSpell takes nothing returns boolean
        if GetSpellAbilityId() == SPELL_ID then
            call SpellActions()
        endif
       
        return false
    endfunction
   
    private function onInit takes nothing returns nothing
        local trigger t = CreateTrigger()
       
        // Preloading:
        static if ENABLE_PRELOAD then
       
            local unit u = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'Hpal', 0, 0, 0)
            call UnitAddAbility(u, SPELL_ID)
            call RemoveUnit(u)
            call Preload(ZAP_EFFECT)
            call Preload(EFFECT)
            set u = null
           
        endif
       
        // Timers:
        set textTagTimer = NewTimer()
        set zapTimer = NewTimer()
        set updateTimer = NewTimer()
       
        // Register the spell:
        call TriggerAddCondition(t, Condition(function CheckSpell))
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        set t = null
    endfunction

endlibrary

Changelogs


v1.3 (10 July 2012)
- All texttags are now updated by one timer instead of a periodic trigger.
- The zapping of positive units by negative units is now handled by one timer.
- Each affected unit's time remaining is now updated by a single timer.
- Added an effect at the target point.
- Made the texttag offset, texttag height and update frequency configurable (advanced users).
- Other minor code improvements.

v1.2 (26 June 2012)
- Fixed it so you can customise the spell AoE.
- Coded my own lightning so you can change what the lightning looks like, how long it lasts and the effect it creates when a unit is zapped. Thanks to KnnO.
- Because of the above change, the dummy unit and ability are no longer needed. Instead TimerUtils is needed.
- The creeps in the demo map are now owned by Neutral Hostile and not by Player 1 :p
- If you enable preloading, the effects are now preloaded too.

v1.1 (26 June 2012)
- Added a new preview image.
- Reduced mana cost of the spell in the demo map.
- Added a cooldown for the spell in the demo map.
- You can now configure the colour of the floating text that shows a - or + above affected units.

v1.0 (26 June 2012)
- Initial release

Credits


- Sage Chow for the spell idea.

Contact


If you find any bugs in the system or if something is unclear in the documentation, please let me know!
- Email
- Private Message

Keywords:
electricity, polarize, polarise, mr_bean, sage chow
Contents

Polarisation (Map)

Reviews
Moderator
00:22, 17th Jul 2012 Magtheridon96: Very original, solid, well-written and readable. Approved. Instead of using those BJs to get the number of units in each group, it would be better to just keep track of the counts yourself. (Using integer...
  1. 00:22, 17th Jul 2012
    Magtheridon96: Very original, solid, well-written and readable. Approved.

    Comments
    • Instead of using those BJs to get the number of units in each
      group, it would be better to just keep track of the counts yourself.
      (Using integer variables)
    • Snippet
      Code (vJASS):
      if IsPlayerAlly(GetLocalPlayer(), p) then
          call SetTextTagVisibility(tt, true)
      endif

      This can be shortened to one line. I'll let you figure out how on your own ;)
    • It's completely fine that you're using those ForGroup calls, but
      there are faster, more efficient ways to handle these kinds of things.
      A linked list would make it much faster. I'm still totally fine with this.
      I will approve it with the current method. ;)
    • It would be better to cache things into local variables instead of
      recalling them. For example, in your ZapPositivesEnum function, it would
      be much better if you were to cache GetHandleId(temp) into a local
      variable.


    I won't rate it now, but if changes are done, it will get a solid 4.3/5.
    (Because I really don't want to give this baby a "Useful - 3" rating)

    Excellent work.
     
  2. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    Update:
    - Added a new preview image.
    - Reduced mana cost of the spell in the demo map.
    - Added a cooldown for the spell in the demo map.
    - You can now configure the colour of the floating text that shows a - or + above affected units.
     
  3. KnnO

    KnnO

    Joined:
    Sep 18, 2011
    Messages:
    156
    Resources:
    3
    Icons:
    1
    Maps:
    1
    Spells:
    1
    Resources:
    3
    [​IMG] I like the preload idea
    [​IMG] Suggestion:
    function RegisterUnit
    should exclude the caster

    [tr]
    [titletd][​IMG][/titletd]
    [tdalt]For Me: I would manually make the lightning
    [/tdalt][/tr]
     
  4. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    Thanks for the feedback! I designed it so that you charge any unit, provided they are alive and not magic immune or a structure. I think I will code the lightning, just didn't feel like it at the time :p
    I will also make the area of effect configurable. It is currently hard-coded at 300.

    Also, I was wondering about
    GroupPickRandomUnit
    . Is this safe to use? I looked at it and it didn't look bad...
     
  5. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    Update: (v1.2)
    - Fixed it so you can customise the spell AoE.
    - Coded my own lightning so you can change what the lightning looks like, how long it lasts and the effect it creates when a unit is zapped. Thanks to KnnO.
    - Because of the above change, the dummy unit and ability are no longer needed. Instead TimerUtils is needed.
    - The creeps in the demo map are now owned by Neutral Hostile and not by Player 1 :p
    - If you enable preloading, the effects are now preloaded too.
     
  6. KnnO

    KnnO

    Joined:
    Sep 18, 2011
    Messages:
    156
    Resources:
    3
    Icons:
    1
    Maps:
    1
    Spells:
    1
    Resources:
    3
    When I read your code I though about that too XD
    blizzard jass functions aren't safe when you can DO the same thing in a less shorter code, or less variables..
    For this I guess it's safe :)
     
  7. xorkatoss

    xorkatoss

    Joined:
    Jul 12, 2010
    Messages:
    1,590
    Resources:
    7
    Models:
    5
    Maps:
    1
    Spells:
    1
    Resources:
    7
    wow awesome idea and execution!! 5/5 +rep :thumbs_up:
     
  8. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    Thanks, but this wasn't my idea. I just coded it :p
     
  9. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    Dude I suggest you use timers instead of TriggerRegisterTimerEvent so that you can pause the timer...or just disable the trigger running those instances if no instances is running...

    CheckSpell and SpellActions should be combined and Timer32 or CTL is better for this since you're running in 0.03...
     
  10. CoLd Bon3

    CoLd Bon3

    Joined:
    Aug 8, 2010
    Messages:
    945
    Resources:
    4
    Spells:
    4
    Resources:
    4
    This spell is... the best thing i have ever seen in my f*cking life. I don't have a damn about Jass, so i can't comment the code... the spell is awesome. 5/5 & +rep!
     
  11. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    Haha, thanks! Glad you liked it :D
     
  12. Deaod

    Deaod

    Joined:
    Nov 18, 2007
    Messages:
    805
    Resources:
    12
    Maps:
    1
    Spells:
    11
    Resources:
    12
    Heres whats wrong in my opinion:
    • StringHash()
      instead of
      key
      s
    • Periodic triggers instead of periodic timers
    • Making texttags visible asynchronously instead of creating them asynchronously
    • Hashtable instead of simply using a unit indexer
    • Using a periodic timer per Lightning instance instead of a single timer for all, or any other similar solution
    • Using your own temporary group instead of using the one provided by GroupUtils
    • Myriads of hardcoded values that are either nondescriptive or prone to change.
     
  13. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    What's right in your opinion? No nice words about the spell?

    Anyway;
    - I will replace StringHash with key.
    - The "myriads" of hard-coded values are the timer durations (0.03) and texttag height and offset. Is it really necessary to make these configurable?
    - I don't use GroupUtils...is it really needed to use it?
    - I will look into making your other improvements...
     
  14. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    1 - Normal intergers as keys
    2 - HT is OK even if UI is faster
    3 - GroupUtils is slow, uses 2 hashtables plus he's looping by EnumUnit in the group, not in area
     
  15. Deaod

    Deaod

    Joined:
    Nov 18, 2007
    Messages:
    805
    Resources:
    12
    Maps:
    1
    Spells:
    11
    Resources:
    12
    Which should be plan B after trying to use a unit indexer.

    Yes, if for nothing else than readability. Ive actually had to adjust the frequency of execution for some spells to decrease workload.

    Well, you dont create groups dynamically, so not every part of GroupUtils is needed. But GroupUnitsInArea could be used, as well as the ENUM_GROUP GroupUtils provides (which is what i was referring to).

    Of course its "OK". If the standard for acceptance is "Works", then many things are "OK". But IMO, "Works" is not enough. An elegant, efficient solution (no, dont go over the top with optimizations) is needed.

    Yes, but GroupUtils is an external library that can be used by multiple spells/libraries so the cost of it is shared. Also, GroupUnitsInArea is exactly what he would want to use for this spell.
    And how is GroupUtils slow if all youre using is the ENUM_GROUP variable? Besides this utterly ridiculous claim, whats wrong with being a bit slower? Theres a tradeoff between API elegance and implementation efficiency that you have to make. In almost all cases it should be decided in favor of API elegance. Theres a huge trend to optimize EVERYTHING to maximum extent possible. With the result that noone can read the libraries because they look like shit due to all the hacks that have to be employed to get the intended result.
    Really, write code that is easy to maintain. If its a tad bit slower than a more efficient solution that is much harder to understand, so what?
     
  16. Lambdadelta

    Lambdadelta

    Joined:
    Jul 6, 2009
    Messages:
    721
    Resources:
    1
    Maps:
    1
    Resources:
    1
    In SpellActions function you use
    u
    only once, so you don't need
    GetTriggerUnit
    as a variable.
     
  17. Mr_Bean

    Mr_Bean

    Joined:
    Feb 11, 2011
    Messages:
    1,823
    Resources:
    6
    Maps:
    2
    Spells:
    4
    Resources:
    6
    Update:
    Finally uploaded version 1.3, which includes improvements mentioned by Deaod:
    - All texttags are now updated by one timer instead of a periodic trigger.
    - The zapping of positive units by negative units is now handled by one timer.
    - Each affected unit's time remaining is now updated by a single timer.
    - Added an effect at the target point.
    - Made the texttag offset, texttag height and update frequency configurable (advanced users).
    - Other minor code improvements.