1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. The Lich King demands your service! We've reached the 19th edition of the Icon Contest. Come along and make some chilling servants for the one true king.
    Dismiss Notice
  4. The 4th SFX Contest has started. Be sure to participate and have a fun factor in it.
    Dismiss Notice
  5. The poll for the 21st Terraining Contest is LIVE. Be sure to check out the entries and vote for one.
    Dismiss Notice
  6. The results are out! Check them out.
    Dismiss Notice
  7. Don’t forget to sign up for the Hive Cup. There’s a 555 EUR prize pool. Sign up now!
    Dismiss Notice
  8. The Hive Workshop Cup contest results have been announced! See the maps that'll be featured in the Hive Workshop Cup tournament!
    Dismiss Notice
  9. 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.

Icon/Model/Spell Team Contest - Hive Member[+100 Rep]

Discussion in 'Contest Archive' started by IcemanBo, Nov 5, 2017.

Thread Status:
Not open for further replies.
  1. Daffa the Mage

    Daffa the Mage

    Map Moderator

    Joined:
    Jan 30, 2013
    Messages:
    7,730
    Resources:
    28
    Packs:
    1
    Maps:
    8
    Spells:
    17
    Tutorials:
    2
    Resources:
    28
    @KILLCIDE Thank you for using GUI, I was afraid I'm the old guy here :D

    My laptop got broke and can't get on the spell till 28 or 29, so next preview and final entry around the 29 and 30. There also has been quite a change of plans.
     
  2. MyPad

    MyPad

    Spell Reviewer

    Joined:
    May 9, 2014
    Messages:
    1,324
    Resources:
    7
    Models:
    1
    Icons:
    2
    Spells:
    3
    JASS:
    1
    Resources:
    7
    Finally, I am finished with the model. It's a bit rushed on @Darkfang 's former avatar, but it's ready to be seen now:

    Final Model

    [​IMG]


    ^^ Quite legendary!
     
  3. Daffa the Mage

    Daffa the Mage

    Map Moderator

    Joined:
    Jan 30, 2013
    Messages:
    7,730
    Resources:
    28
    Packs:
    1
    Maps:
    8
    Spells:
    17
    Tutorials:
    2
    Resources:
    28
    The deadline is 30 November 23:59 GMT right? I want to confirm the time left.
     
  4. Flux

    Flux

    Joined:
    Feb 6, 2014
    Messages:
    2,333
    Resources:
    28
    Maps:
    1
    Spells:
    19
    Tutorials:
    2
    JASS:
    6
    Resources:
    28
    Nope.
     
  5. MyPad

    MyPad

    Spell Reviewer

    Joined:
    May 9, 2014
    Messages:
    1,324
    Resources:
    7
    Models:
    1
    Icons:
    2
    Spells:
    3
    JASS:
    1
    Resources:
    7
    It ends on 30 December 23:59 +08:00 on mine.
     
  6. IcemanBo

    IcemanBo

    Joined:
    Sep 6, 2013
    Messages:
    6,180
    Resources:
    22
    Maps:
    3
    Spells:
    11
    Template:
    1
    Tutorials:
    4
    JASS:
    3
    Resources:
    22
    What?.. what's the current state or exact lack? Or there's just absolutly nothing?
    Is there an issue with the info from main post? It's clearly stated 30th Dec GMT (day included) ...
     
  7. Daffa the Mage

    Daffa the Mage

    Map Moderator

    Joined:
    Jan 30, 2013
    Messages:
    7,730
    Resources:
    28
    Packs:
    1
    Maps:
    8
    Spells:
    17
    Tutorials:
    2
    Resources:
    28
    Nothing wrong with the first post. I'm just that too doubtful guy, sorry.
     
  8. KILLCIDE

    KILLCIDE

    Administrator

    Joined:
    Jul 22, 2015
    Messages:
    3,501
    Resources:
    20
    Models:
    2
    Icons:
    10
    Spells:
    7
    Tutorials:
    1
    Resources:
    20
    @IcemanBo @Murlocologist just in case it was missed, I posted my 2nd code WIP.

    GUI always and forever.

    EDIT
    ===

    Going to keep this thread alive for the last few days, so here is my 3rd WIP! I finished the "red paint" mechanic :D

    GIF
    WIP.gif


    Two more to go ;_;


    Config
    • RPaint Config
      • Events
        • Map initialization
      • Conditions
      • Actions
        • -------- --------
        • -------- CONFIG START --------
        • -------- --------
        • -------- --------
        • -------- imported triggers --------
        • Set RPaint_TRIGGER_LOOP = RPaint Loop <gen>
        • -------- --------
        • -------- damage dealt to nearby enemy units when the bubble explodes --------
        • Set RPaint_DAMAGE = 50.00
        • Set RPaint_DAMAGE_PER_LEVEL = 25.00
        • -------- --------
        • -------- how close a unit must be to the bubble to take damage --------
        • Set RPaint_AOE = 250.00
        • Set RPaint_AOE_PER_LEVEL = 0.00
        • -------- --------
        • -------- time (in seconds) it takes for the bubble to pop and deal damage --------
        • Set RPaint_POP_DELAY = 2.00
        • Set RPaint_POP_DELAY_PER_LEVEL = 0.00
        • -------- --------
        • -------- time (in seconds) it takes for the bubble to pop and deal damage --------
        • Set RPaint_POP_DELAY = 2.00
        • Set RPaint_POP_DELAY_PER_LEVEL = 0.00
        • -------- --------
        • -------- special effect for puddle --------
        • Set RPaint_SFX_PUDDLE = PaintBombPuddle_Red.mdl
        • Set RPaint_SFX_PUDDLE_AP = origin
        • Set RPaint_SFX_PUDDLE_SIZE = 1.00
        • Set RPaint_SFX_PUDDLE_DEATH_TIMER = 0.25
        • -------- ^ how much time (in seconds) is needed for death sfx to play --------
        • -------- --------
        • -------- special effect for bubble --------
        • Set RPaint_SFX_BUBBLE = PaintBombBubble.mdl
        • Set RPaint_SFX_BUBBLE_AP = origin
        • Set RPaint_SFX_BUBBLE_START_SIZE = 1.00
        • Set RPaint_SFX_BUBBLE_FINAL_SIZE = 2.50
        • Set RPaint_SFX_BUBBLE_DEATH_TIMER = 1.00
        • -------- ^ how much time (in seconds) is needed for death sfx to play --------
        • -------- --------
        • -------- other --------
        • Set RPaint_ATTACK_TYPE = Spells
        • Set RPaint_DAMAGE_TYPE = Magic
        • Set RPaint_PERIODIC_TIMER = 0.03
        • -------- --------
        • -------- --------
        • -------- CONFIG END --------
        • -------- --------
        • Trigger - Add to RPaint_TRIGGER_LOOP the event (Time - Every RPaint_PERIODIC_TIMER seconds of game time)
        • -------- preload --------
        • Custom script: set udg_RPaint_TempUnit = GetRecycledDummyAnyAngle(0.00, 0.00, 0.00)
        • Special Effect - Create a special effect attached to the RPaint_SFX_PUDDLE_AP of RPaint_TempUnit using RPaint_SFX_PUDDLE
        • Special Effect - Destroy (Last created special effect)
        • Special Effect - Create a special effect attached to the RPaint_SFX_BUBBLE_AP of RPaint_TempUnit using RPaint_SFX_BUBBLE
        • Special Effect - Destroy (Last created special effect)
        • Custom script: call RecycleDummy(udg_RPaint_TempUnit)
        • -------- math calculations --------
        • Set RPaint_SFX_PUDDLE_SIZE = (RPaint_SFX_PUDDLE_SIZE x 100.00)
        • Set RPaint_SFX_BUBBLE_START_SIZE = (RPaint_SFX_BUBBLE_START_SIZE x 100.00)
        • Set RPaint_SFX_BUBBLE_FINAL_SIZE = (RPaint_SFX_BUBBLE_FINAL_SIZE x 100.00)
        • Set RPaint_BubbleSizeSfx = (RPaint_SFX_BUBBLE_FINAL_SIZE - RPaint_SFX_BUBBLE_START_SIZE)


    Index
    • RPaint Index
      • Events
      • Conditions
      • Actions
        • -------- PBomb Index Red --------
        • -------- this trigger will create a new instance for the Red Paint Mechanic --------
        • -------- --------
        • -------- members --------
        • -------- Caster[] - unit that will deal the damage when the paint bubble explodes --------
        • -------- Owner[] - player who owns Caster[] --------
        • -------- CurrentColor[] - the color the caster had selected when they threw the paint bomb --------
        • -------- CurrentSize[] - the current size of the bubble as it grows periodically --------
        • -------- Damage[] - damage dealt to nearby enemy units when the bubble explodes --------
        • -------- PuddleLoc[] - center of the explosion --------
        • -------- Radius[] - distance units must be from PuddleLoc[] to take damage --------
        • -------- PuddleUnit[] - dummy unit with the puddle special effect --------
        • -------- PuddleSfx[] - the special effect for the puddle left on the ground --------
        • -------- BubbleUnit[] - dummy unit with the bubble special effect --------
        • -------- BubbleSfx[] - the special effect for the bubble --------
        • -------- GrowRate[] - how fast BubbleUnit[] will change in size per iteration --------
        • -------- --------
        • -------- --------
        • Custom script: local real x
        • Custom script: local real y
        • -------- --------
        • Set RPaint_SpellCount = (RPaint_SpellCount + 1)
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • RPaint_SpellCount Equal to 1
          • Then - Actions
            • Trigger - Turn on RPaint_TRIGGER_LOOP
          • Else - Actions
            • -------- do nothing --------
        • -------- --------
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • RPaint_RecycledSize Equal to 0
          • Then - Actions
            • Set RPaint_MaxIndex = (RPaint_MaxIndex + 1)
            • Set RPaint_SpellId = RPaint_MaxIndex
          • Else - Actions
            • Set RPaint_RecycledSize = (RPaint_RecycledSize - 1)
            • Set RPaint_SpellId = RPaint_RecycledStack[RPaint_RecycledSize]
        • Set RPaint_NodeNext[RPaint_SpellId] = 0
        • Set RPaint_NodePrev[RPaint_SpellId] = RPaint_NodePrev[0]
        • Set RPaint_NodeNext[RPaint_NodePrev[0]] = RPaint_SpellId
        • Set RPaint_NodePrev[0] = RPaint_SpellId
        • -------- --------
        • Set RPaint_Caster[RPaint_SpellId] = PBomb_Caster[PBomb_SpellId]
        • Set RPaint_Owner[RPaint_SpellId] = PBomb_Owner[PBomb_SpellId]
        • Set RPaint_CurrentColor[RPaint_SpellId] = PBomb_CurrentColor[PBomb_SpellId]
        • Set RPaint_CurrentSize[RPaint_SpellId] = RPaint_SFX_BUBBLE_START_SIZE
        • -------- --------
        • Set RPaint_TempReal = (Real(PBomb_AbilityLvl[PBomb_SpellId]))
        • Set RPaint_Damage[RPaint_SpellId] = (RPaint_DAMAGE + (RPaint_DAMAGE_PER_LEVEL x RPaint_TempReal))
        • Set RPaint_Radius[RPaint_SpellId] = (RPaint_AOE + (RPaint_AOE_PER_LEVEL x RPaint_TempReal))
        • Set RPaint_GrowRate[RPaint_SpellId] = (RPaint_BubbleSizeSfx / ((RPaint_POP_DELAY + (RPaint_POP_DELAY_PER_LEVEL x RPaint_TempReal)) / RPaint_PERIODIC_TIMER))
        • -------- --------
        • Set RPaint_PuddleLoc[RPaint_SpellId] = (Position of PBomb_MissileUnit[PBomb_SpellId])
        • Custom script: set x = GetLocationX(udg_RPaint_PuddleLoc[udg_RPaint_SpellId])
        • Custom script: set y = GetLocationY(udg_RPaint_PuddleLoc[udg_RPaint_SpellId])
        • Custom script: set udg_RPaint_PuddleUnit[udg_RPaint_SpellId] = GetRecycledDummyAnyAngle(x, y, 0.00)
        • Animation - Change RPaint_PuddleUnit[RPaint_SpellId]'s size to (RPaint_SFX_PUDDLE_SIZE%, 100.00%, 100.00%) of its original size
        • Special Effect - Create a special effect attached to the RPaint_SFX_PUDDLE_AP of RPaint_PuddleUnit[RPaint_SpellId] using RPaint_SFX_PUDDLE
        • Set RPaint_PuddleSfx[RPaint_SpellId] = (Last created special effect)
        • -------- --------
        • Custom script: set udg_RPaint_BubbleUnit[udg_RPaint_SpellId] = GetRecycledDummyAnyAngle(x, y, 0.00)
        • Animation - Change RPaint_BubbleUnit[RPaint_SpellId]'s size to (RPaint_SFX_BUBBLE_START_SIZE%, 100.00%, 100.00%) of its original size
        • Special Effect - Create a special effect attached to the RPaint_SFX_BUBBLE_AP of RPaint_BubbleUnit[RPaint_SpellId] using RPaint_SFX_BUBBLE
        • Set RPaint_BubbleSfx[RPaint_SpellId] = (Last created special effect)


    Loop
    • RPaint Loop
      • Events
      • Conditions
      • Actions
        • -------- RPaint Loop --------
        • -------- this trigger will periodically grow the bubble --------
        • -------- once the bubble reaches the max size, it will explode, and deal damage to nearby enemy units --------
        • -------- --------
        • -------- members --------
        • -------- Caster[] - unit that will deal the damage when the paint bubble explodes --------
        • -------- Owner[] - player who owns Caster[] --------
        • -------- CurrentColor[] - the color the caster had selected when they threw the paint bomb --------
        • -------- CurrentSize[] - the current size of the bubble as it grows periodically --------
        • -------- Damage[] - damage dealt to nearby enemy units when the bubble explodes --------
        • -------- PuddleLoc[] - center of the explosion --------
        • -------- Radius[] - distance units must be from PuddleLoc[] to take damage --------
        • -------- PuddleUnit[] - dummy unit with the puddle special effect --------
        • -------- PuddleSfx[] - the special effect for the puddle left on the ground --------
        • -------- BubbleUnit[] - dummy unit with the bubble special effect --------
        • -------- BubbleSfx[] - the special effect for the bubble --------
        • -------- GrowRate[] - how fast BubbleUnit[] will change in size per iteration --------
        • -------- --------
        • -------- --------
        • Set RPaint_SpellId = 0
        • For each (Integer RPaint_LoopInt) from 1 to RPaint_SpellCount, do (Actions)
          • Loop - Actions
            • Set RPaint_SpellId = RPaint_NodeNext[RPaint_SpellId]
            • -------- --------
            • -------- checking if the bubble has reached the max size --------
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • RPaint_CurrentSize[RPaint_SpellId] Greater than or equal to RPaint_SFX_BUBBLE_FINAL_SIZE
              • Then - Actions
                • -------- bubble has reached max size; damage nearby enemy units and deallocate --------
                • -------- --------
                • -------- using GroupEnumUnitsInRangeOfLoc because GetUnitsInRangeOfLoc has a reference handle leak --------
                • Custom script: call GroupEnumUnitsInRangeOfLoc(udg_PBomb_InRangeGroup, udg_RPaint_PuddleLoc[udg_RPaint_SpellId], udg_RPaint_Radius[udg_RPaint_SpellId], null)
                • Unit Group - Pick every unit in PBomb_InRangeGroup and do (Actions)
                  • Loop - Actions
                    • Set RPaint_TempUnit = (Picked unit)
                    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                      • If - Conditions
                        • (RPaint_TempUnit is A structure) Equal to False
                        • (RPaint_TempUnit is Magic Immune) Equal to False
                        • (RPaint_TempUnit is alive) Equal to True
                        • (RPaint_TempUnit belongs to an enemy of RPaint_Owner[RPaint_SpellId]) Equal to True
                      • Then - Actions
                        • Unit - Cause RPaint_Caster[RPaint_SpellId] to damage RPaint_TempUnit, dealing RPaint_Damage[RPaint_SpellId] damage of attack type RPaint_ATTACK_TYPE and damage type RPaint_DAMAGE_TYPE
                      • Else - Actions
                        • -------- do nothing --------
                    • Unit Group - Remove RPaint_TempUnit from PBomb_InRangeGroup
                • -------- --------
                • Custom script: set udg_SPaint_UnitId = GetHandleId(udg_RPaint_Caster[udg_RPaint_SpellId])
                • Hashtable - Save ((Load PBomb_KEY_ACTIVE_COUNT[RPaint_CurrentColor[RPaint_SpellId]] of SPaint_UnitId from PBomb_Hash) - 1) as PBomb_KEY_ACTIVE_COUNT[RPaint_CurrentColor[RPaint_SpellId]] of SPaint_UnitId in PBomb_Hash
                • -------- --------
                • Custom script: call RemoveLocation(udg_RPaint_PuddleLoc[udg_RPaint_SpellId])
                • Special Effect - Destroy RPaint_PuddleSfx[RPaint_SpellId]
                • Special Effect - Destroy RPaint_BubbleSfx[RPaint_SpellId]
                • Custom script: call DummyAddRecycleTimer(udg_RPaint_PuddleUnit[udg_RPaint_SpellId], udg_RPaint_SFX_PUDDLE_DEATH_TIMER)
                • Custom script: call DummyAddRecycleTimer(udg_RPaint_BubbleUnit[udg_RPaint_SpellId], udg_RPaint_SFX_BUBBLE_DEATH_TIMER)
                • Set RPaint_RecycledStack[RPaint_RecycledSize] = RPaint_SpellId
                • Set RPaint_RecycledSize = (RPaint_RecycledSize + 1)
                • Set RPaint_NodeNext[RPaint_NodePrev[RPaint_SpellId]] = RPaint_NodeNext[RPaint_SpellId]
                • Set RPaint_NodePrev[RPaint_NodeNext[RPaint_SpellId]] = RPaint_NodePrev[RPaint_SpellId]
                • -------- --------
                • Set RPaint_SpellCount = (RPaint_SpellCount - 1)
                • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • RPaint_SpellCount Equal to 0
                  • Then - Actions
                    • Trigger - Turn off RPaint_TRIGGER_LOOP
                  • Else - Actions
                    • -------- do nothing --------
              • Else - Actions
                • -------- bubble has not reached max size; continue to grow --------
                • Set RPaint_CurrentSize[RPaint_SpellId] = (RPaint_CurrentSize[RPaint_SpellId] + RPaint_GrowRate[RPaint_SpellId])
                • Animation - Change RPaint_BubbleUnit[RPaint_SpellId]'s size to (RPaint_CurrentSize[RPaint_SpellId]%, 100.00%, 100.00%) of its original size
     
    Last edited: Dec 28, 2017
  9. Misha

    Misha

    Joined:
    Jun 9, 2008
    Messages:
    7,206
    Resources:
    71
    Models:
    62
    Icons:
    1
    Packs:
    2
    Skins:
    4
    StarCraft II Resources:
    2
    Resources:
    71
    @KILLCIDE the paint mechanic is really nice :)
     
  10. MyPad

    MyPad

    Spell Reviewer

    Joined:
    May 9, 2014
    Messages:
    1,324
    Resources:
    7
    Models:
    1
    Icons:
    2
    Spells:
    3
    JASS:
    1
    Resources:
    7
    Is it okay to use lua script? I kind of went out of my way and also created one for the spell.

    Code (vJASS):

    //! externalblock extension=lua ObjectMerger $FILENAME$
            //! i ID = "e002"
         
            //! i ATTACK_SPEED = 1.0
            //! i MOVE_SPEED = 500
            //! i NAME = "Fel Spiderling"
         
            //! i function declare_spider(atkSpeed, mvSpeed, paramName)
            //! i setobjecttype("units")
             
            //! i createobject("nspd", ID)

            //! i makechange(current, "uico", "ReplaceableTextures\CommandButtons\BTNSpiderBlack.blp")
            //! i makechange(current, "umdl", "units\creeps\SpiderBlack\SpiderBlack.mdl")
             
            //! i makechange(current, "usca", 0.4)
            //! i makechange(current, "ussc", 0.9)
             
            //! i makechange(current, "ushx", 15)
            //! i makechange(current, "ushy", 15)
            //! i makechange(current, "ushh", 40)
            //! i makechange(current, "ushw", 40)
           
            //! i makechange(current, "ua1t", "chaos")
            //! i makechange(current, "ua1c", math.min(math.max(atkSpeed, 0.1), 5.0))
            //! i makechange(current, "ua1b", 0)
            //! i makechange(current, "ua1s", 1)
            //! i makechange(current, "ua1d", 1)
            //! i makechange(current, "ua1r", 90)
           
            //! i makechange(current, "umvs", math.min(mvSpeed, 522))
            //! i makechange(current, "umas", math.min(mvSpeed, 522))
            //! i makechange(current, "umis", math.min(mvSpeed - 1, 100))
           
            //! i makechange(current, "uhpm", 250)
            //! i makechange(current, "urac", "undead")
           
            //! i makechange(current, "unam", paramName)
            //! i makechange(current, "utip", "Summon " .. paramName)
            //! i makechange(current, "utub", "Light melee unit. Deals damage based on attribute. |n|n|cffffcc00Attacks land units.|r")
        //! i end
         
        //! i declare_spider(ATTACK_SPEED, MOVE_SPEED, NAME)
    //! endexternalblock
     


    Also, this is the final code WIP before submission.

    Code (vJASS):

    library OvermindSpellThree initializer Init requires /*

        *   ----------------------
        */
     AllocationAndLinks, /*  https://www.hiveworkshop.com/threads/allocation-and-links.293621/
        *   ----------------------
        *
        *       -   Contains the doubly linked list and custom allocation which is preferred by the coder.
        *       -   If you don't want extends array syntax, just change AllocLinkBundle to DoubleLink
        *          
        *   ----------------------
        */
     TimerUtils,         /*  http://www.wc3c.net/showthread.php?t=101322
        *   ----------------------
        *
        *       -   Too lazy to create a timer library that allows attachment of data,
        *           but not too lazy to completely rewrite it.
        *
        *   ----------------------------
        */
     CustomFunctions,          /*
        *   ----------------------------
        *
        *       -   Allows a nice not-red debug setting, and allows the instant generation of a search function.
        *           Technically not useless.
        *
        *   --------------------------------
        */
     DamageEvent,   DamageModify,  /*    https://www.hiveworkshop.com/threads/damagepackage.287101/
        *   --------------------------------
        *
        *       -   Allows the manipulation of damage
        *       -   DamageModify is the takeaway here. (Modifies the damage dealt by the spiderlings).
        *
        *   --------------------------------
        */
     optional TextTag              /*    https://www.hiveworkshop.com/threads/library-text-tag.290924/page-2#post-3138916
        *   --------------------------------
        *       -   Optionally displays the amount restored to the hive creator.
        *       -   Can be used informationally.
        *
        */

       
        /*
        *   __________________________
        *      
        *       OvermindSpellThree
        *   __________________________
        *
        *       ______________
        *      
        *          The Hive
        *       ______________
        *
        *           -   A spell based on Pocket Factory that plants a targeted location with a hive mind.
        *           -   This spell is active, and has a sub-spell component, namely Ravage Hive.
        *
        *       __________________
        *                      
        *          How it goes
        *       __________________
        *
        *           -   The spell is cast, triggering a spell-effect trigger and creating an associated
        *               struct instance of type Data.
        *
        *           -   The Data struct instance then activates a timer, which is set to expire based on
        *               the speed of the missile created by the ability and the distance therefrom.
        *
        *           -   After expiration, the hive is created with a delay in its' timed life. During this
        *               time, the hive is rendered invulnerable.
        *
        *           -   After the delay, the expiration timer for the hive is started. The hive may or may
        *               not be harmed based on the data flag section.
        *
        *           -   If it dies, its' expiration timer expires, or a Ravage Hive sub-spell has taken effect,
        *               the hive will execute its' death-related event. This may bug out with certain scripts,
        *               which remove units on death.
        *
        *       ____________
        *      
        *           API
        *       ____________
        *
        *           native functions:
        *               -   UnitAlive(unit id) returns boolean
        *
        *           external functions:
        *               -   external func:
        *                       exe:    ObjectMerger.exe
        *                       type:   w3u / units
        *                       base id:    'hfoo'  /   footman
        *                       new id:     '!000'  /   footman derivative.
        *                      
        *                       model:  "dummy.mdx"
        *
        *           globals:
        *               private constant group ENUM_GROUP
        *                   -   Enumerator group
        *               private unit enum_unit
        *                   -   Enumerator unit variable.
        *
        *           configurable functions:
        *               function SPELL_ID() returns integer
        *                   -   Returns the raw code of the spell. (See in Object Editor (Ctrl + D))
        *               function RAW_ID(int i) returns integer
        *                   -   Returns some raw code based on request. (Defaults to 0)
        *               function DATA(int i, int lev) returns real
        *                   -   Returns the necessary soft-coded data field. (Defaults to 0)
        *
        *       External scripts:
        *           -   Used mostly for the generation of the spiderling with the added speed properties.
        *               Can be modified to a certain extent by script.
        *
        */

           
        native UnitAlive takes unit id returns boolean
       
       
        /*  The following scripts are external lua scripts which generate the necessary unit data.
        *   Since I wanted to make this configurable (to a certain extent), the script for declaring
        *   a spider is given below.
        *  
        *   This line of code has been deemed redundant due to the pathing script being removed.
        *   ___________________________________________________________
        *
        *   ///! external ObjectMerger w3u hfoo "!000" umdl "dummy.mdx"
        *   ___________________________________________________________
        *
        *   The code below may be commented out by adding a delimited comment.
        *   Delimited comments look like this:
        *
        *   /*
        *       Put some stuff here.
        *   */

        *
        *   To enable the script again, just remove the delimiters.
        *
        *   ___________
        *
        *       API
        *   ___________
        *
        *       ID = "char"
        *           -   The rawcode of the spider.
        *
        *       ATTACK_SPEED = float r
        *           -   The attack speed defined as a float.
        *       MOVE_SPEED = float r
        *           -   The movement speed of the spider defined as an integer.
        *       NAME = string nam
        *           -   The name of the spider. If you like, you can change it.
        *
        *       function declare_spider(real atkSpeed, int mvSpeed, string paramName)
        *           - Due to the lack of explicit type definition, the type of the parameters have been
        *             supplied for you.
        *
        *           - Generates a spider with a certain raw id based on the ID variable (string)
        *           - The only configurable parts are the attack speed, move speed and name
        *             Even then, the attack speed is capped off at 5.0 and 0.1.
        *
        *           - Will cause the Typecasting library to fail if the external script is not delimited.
        */
       
        /*
        //! externalblock extension=lua ObjectMerger $FILENAME$
            //! i ID = "e002"
           
            //! i ATTACK_SPEED = 1.0
            //! i MOVE_SPEED = 500
            //! i NAME = "Fel Spiderling"
           
            //! i function declare_spider(atkSpeed, mvSpeed, paramName)
                //! i setobjecttype("units")
               
                //! i createobject("nspd", ID)
               
                //! i makechange(current, "uico", "ReplaceableTextures\\CommandButtons\\BTNSpiderBlack.blp")
                //! i makechange(current, "umdl", "units\\creeps\\SpiderBlack\\SpiderBlack.mdl")
               
                //! i makechange(current, "usca", 0.4)
                //! i makechange(current, "ussc", 0.9)
               
                //! i makechange(current, "ushx", 15)
                //! i makechange(current, "ushy", 15)
                //! i makechange(current, "ushh", 40)
                //! i makechange(current, "ushw", 40)
               
                //! i makechange(current, "ua1t", "chaos")
                //! i makechange(current, "ua1c", math.min(math.max(atkSpeed, 0.1), 5.0))
                //! i makechange(current, "ua1b", 0)
                //! i makechange(current, "ua1s", 1)
                //! i makechange(current, "ua1d", 1)
                //! i makechange(current, "ua1r", 90)
               
                //! i makechange(current, "umvs", math.min(mvSpeed, 522))
                //! i makechange(current, "umas", math.min(mvSpeed, 522))
                //! i makechange(current, "umis", math.min(mvSpeed - 1, 100))
               
                //! i makechange(current, "uhpm", 250)
                //! i makechange(current, "urac", "undead")
               
                //! i makechange(current, "unam", paramName)
                //! i makechange(current, "utip", "Summon " .. paramName)
                //! i makechange(current, "utub", "Light melee unit. Deals damage based on attribute. |n|n|cffffcc00Attacks land units.|r")
            //! i end
           
            //! i declare_spider(ATTACK_SPEED, MOVE_SPEED, NAME)
        //! endexternalblock
        */

       
        globals
            private constant group ENUM_GROUP = CreateGroup()
            private unit enum_unit = null
        endglobals
       
        private constant function SPELL_ID takes nothing returns integer
            return 'A002'
        endfunction
       
        private constant function RAW_ID takes integer request returns integer
            if request == 0 then
                //  Returns the ID of the hatchery.
                return 'e001'
            elseif request == 1 then
                //  Returns the ID of the fel spiderlings
                return 'e002'
            elseif request == 2 then
                //  Returns the ID of the sub-spell
                return '1001'
            endif
            return 0
        endfunction
       
        private constant function DATA takes integer request, integer level returns real
            if request == 0 then
                //  Returns the duration of the hive
                if level == 1 then
                    return 50.
                elseif level == 2 then
                    return 75.
                elseif level == 3 then
                    return 100.
                endif
            elseif request == 1 then
                //  Returns the effective detection range.
                if level == 1 then
                    return 150.
                elseif level == 2 then
                    return 250.
                elseif level == 3 then
                    return 350.
                endif
            elseif request == 2 then
                //  Returns the tick rate.
                //  Defaults to 1.
                return 1.
            elseif request == 3 then
                //  Returns the amount of mana burned around the hive
                if level == 1 then
                    return 5.
                elseif level == 2 then
                    return 7.
                elseif level == 3 then
                    return 10.
                endif
            elseif request == 4 then
                //  Returns the amount of health rejuvenated by ratio.
                //  Only takes effect when used as a nydus canal.
                if level == 1 then
                    return 0.1
                elseif level == 2 then
                    return 0.12
                elseif level == 3 then
                    return 0.16
                endif
            elseif request == 5 then
                //  Returns the range field for allowing mana burn
                //  Defaults to 500.
                return 500.
            elseif request == 6 then
                //  Returns the flag for allowing the hive to be invulnerable.
                //  Defaults to true (not equal to 0.)
                return 0.
            elseif request == 7 then
                //  Returns the damage dealt when hive (simulating death or actually dying)
                if level == 1 then
                    return 85.
                elseif level == 2 then
                    return 150.
                elseif level == 3 then
                    return 220.
                endif
            elseif request == 8 then
                //  Returns the amount of spiders that will spawn.
                if level == 1 then
                    return 4.
                elseif level == 2 then
                    return 5.
                elseif level == 3 then
                    return 6.
                endif
            elseif request == 9 then
                //  Returns the speed of the missile
                //  Must correspond to the object data equivalent.
                return 1000.
            elseif request == 10 then
                //  Returns the frequency of the global timer
                //  Cannot be configured to the level of the unit
                return 1/32.
            elseif request == 11 then
                //  Returns the fade-in total duration.
                //  Cannot be configured to the level of the unit
                return 2.5
            elseif request == 12 then
                //  Returns the duration of the death animation
                //  Cannot be configured to the level of the unit
                return 5.
            elseif request == 13 then
                //  Returns the main attribute to follow
                //  Higher values will return modulo of 3.
                //  Strength: 1
                //  Agility: 2
                //  Intelligence: 3
                return 3.
            elseif request == 14 then
                //  Returns damage dealt based on percentage
                if level == 1 then
                    return 0.1
                elseif level == 2 then
                    return 0.14
                elseif level == 3 then
                    return 0.18
                endif
            elseif request == 15 then
                //  Returns the amount of mana rejuvenated by ratio.
                //  Only takes effect when used as a nydus canal.
                if level == 1 then
                    return 0.12
                elseif level == 2 then
                    return 0.16
                elseif level == 3 then
                    return 0.2
                endif
            endif
            return 0.
        endfunction
       
        /*  Generated boolean comparison (inlined) */
        globals
            private constant boolean REG_11_BOOL = 2.5 <= 0.
        endglobals
       
        /*  The strings which will be used for projecting certain effects and such */
        private constant function MDL_FILE takes integer request returns string
            if request == 0 then
                return "Abilities\\Weapons\\ChimaeraAcidMissile\\ChimaeraAcidMissile.mdl"
            elseif request == 1 then
                return "Abilities\\Spells\\NightElf\\ManaBurn\\ManaBurnTarget.mdl"
            elseif request == 2 then
                return "Abilities\\Weapons\\snapMissile\\snapMissile.mdl"
            elseif request == 3 then
                return "Units\\NightElf\\Wisp\\WispExplode.mdl"
            endif
            return ""
        endfunction
       
        private function real_GetDist takes real x1, real y1, real x2, real y2 returns real
            return SquareRoot((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2))
        endfunction
       
        private function echo takes string s returns nothing
            static if DEBUG_MODE then
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 16, s)
            endif
        endfunction
        //  Generates a module with the name DoubleLink_local. It has the property of a private module.
        //  Same with the next textmacro. A private module DoubleLink_active is generated.
        //! runtextmacro link_module("local", "private")
        //! runtextmacro link_module("active", "private")
       
        private struct Data extends array
            implement AllocLinkBundle
            implement DoubleLink_local
            implement DoubleLink_active
           
            private static constant timer ACTIVE_TIMER = CreateTimer()
            private static constant group STORED_SPIDERS = CreateGroup()
           
            //  Assistant to the stored spider group
            private static integer stored_spider_count = 0
           
            //  Counter for a forGroupEx call
            private static integer spider_group_count = 0
           
            //  Mode checker
            private integer mode
            private real mode_data
           
            /*  Part One
            *       -   This will store the unit, level, timer, target x, and target y for
            *           the successful creation of the hive. */

           
            private unit unit
            private unit hive
           
            private integer level
           
            private timer timer
           
            private real tx
            private real ty
           
            //  Part Two
            /*      -   This will be the main part of the spell, the mechanics of which will
            *           be the main focus and intention of this spell. */

           
            //  For speed purposes
            private static player feedback_player
            private static thistype hive_this
            private static thistype spider_this
           
            private real stored
            private integer eventtype
           
            private unit target
            private trigger detector
           
            private group spider_group
           
            /*
                These textmacros can be found at CustomFunctions. It's easy to port them to this library, though.
                They generate a searching algorithm for finding a certain instance.
               
                If not fully explained, the parameters are defined as follows:
                    search_list(encapsulation-keyword, name, searched type, iterator variable, conditional statement)
            */

           
            //! runtextmacro search_list("private", "get", "unit", "next", "unit == id")
            //! runtextmacro search_list("private", "get_hive", "unit", "active_next", "hive == id")
            //! runtextmacro search_list("private", "get_targ", "unit", "active_next", "target == id")
            //! runtextmacro search_list("private", "get_trig", "trigger", "active_next", "detector == id")
            //! runtextmacro search_list("private", "get_group", "unit", "active_next", "IsUnitInGroup(id, spider_group)")
           
            //  Detaches a certain instance from a global list if it is found and in the local list.
            //  Pushes the next local instance to the global list if there exists at least one more.
            private method detach takes nothing returns nothing
                if head != 0 then
                    if local_next != this then
                        set local_next.head = 1
                       
                        call local_next.insert(next)
                    endif
                    set head = 0
                    call pop()
                endif
                call local_pop()
            endmethod
           
            /*  Mimics death for the spiders    */
            private static method spider_preDestroy_enum takes nothing returns nothing
                set enum_unit = GetEnumUnit()
               
                call PauseUnit(enum_unit, true)
                call SetUnitAnimation(enum_unit, "death")
            endmethod
           
            private method spider_preDestroy takes nothing returns nothing
                call ForGroup(spider_group, function thistype.spider_preDestroy_enum)
               
                set enum_unit = null
            endmethod
           
            /*  Resets the animation for the next group */
            private static method spider_onDestroy_enum takes nothing returns nothing
                set enum_unit = GetEnumUnit()
               
                call QueueUnitAnimation(enum_unit, "stand")
                call SetUnitX(enum_unit, 0)
                call SetUnitY(enum_unit, 0)
               
                call SetUnitOwner(enum_unit, Player(15), true)
                call ShowUnit(enum_unit, false)
            endmethod
           
            private method spider_onDestroy takes nothing returns nothing
                call ForGroup(spider_group, function thistype.spider_onDestroy_enum)
               
                set enum_unit = null
            endmethod
           
            /*  Check if the hive is still alive. If not, attempt to nullify hive and prepare a new one.    */
            private method preDestroy takes nothing returns nothing
                if not UnitAlive(hive) then
                    call RemoveUnit(hive)
                    set hive = null
                else
                    call PauseUnit(hive, true)
                    call ShowUnit(hive, false)
                   
                    call SetUnitX(hive, 0)
                    call SetUnitY(hive, 0)
                   
                    call SetWidgetLife(hive, GetUnitState(hive, UNIT_STATE_MAX_LIFE))
                    call SetUnitOwner(hive, Player(15), false)
                   
                    if not (DATA(6, level) != 0) then
                        call echo("Unit is vulnerable")
                        call UnitRemoveAbility(hive, 'Aloc')
                    debug else
                        call echo("Unit is invulnerable")
                    endif
                endif
            endmethod
           
            private method destroy takes nothing returns nothing
                call spider_onDestroy()
                call preDestroy()
                call ReleaseTimer(timer)
               
                call DestroyTrigger(detector)
               
                set unit = null
                set target = null
               
                set timer = null
                set detector = null
               
                set tx = 0.
                set ty = 0.
                set mode_data = 0.
                set stored = 0.
               
                set head = 0
                set mode = 0
                set eventtype = 0
               
                call active_pop()
               
                set active_head = 0
                set thistype(0).active_head = thistype(0).active_head - 1
               
                call deallocate()
            endmethod
           
            //  Part two
            private static method target_attack_enum takes nothing returns nothing
                local thistype this = spider_this
                set enum_unit = GetEnumUnit()
               
                if target != null then
                    if GetUnitTypeId(target) != 0 or UnitAlive(target) then
                        call IssueTargetOrder(enum_unit, "attack", target)
                    else
                        call IssuePointOrder(enum_unit, "move", GetUnitX(hive) + GetRandomReal(-DATA(1, level), DATA(1, level)), GetUnitY(spider_this.hive) + GetRandomReal(-DATA(1, level), DATA(1, level)))
                    endif
                else
                    call IssuePointOrder(enum_unit, "move", GetUnitX(hive) + GetRandomReal(-DATA(1, level), DATA(1, level)), GetUnitY(hive) + GetRandomReal(-DATA(1, level), DATA(1, level)))
                endif
            endmethod
           
            private method target_attack takes nothing returns nothing
                set spider_this = this
               
                call ForGroup(spider_group, function thistype.target_attack_enum)
                   
                set spider_this = 0
            endmethod
           
            private method target_search takes nothing returns nothing
                set feedback_player = GetOwningPlayer(hive)
               
                call GroupEnumUnitsInRange(ENUM_GROUP, GetUnitX(hive), GetUnitY(hive), DATA(1, level), null)
                call GroupRemoveUnit(ENUM_GROUP, target)
                loop
                    set enum_unit = FirstOfGroup(ENUM_GROUP)
                    exitwhen enum_unit == null
                   
                    if UnitAlive(enum_unit) and IsUnitEnemy(enum_unit, feedback_player) and UnitDamageTarget(enum_unit, enum_unit, 0, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null) then
                        set target = enum_unit
                       
                        exitwhen true
                    endif
                   
                    call GroupRemoveUnit(ENUM_GROUP, enum_unit)
                endloop
                if enum_unit == null then
                    set target = null
                    call echo("No valid target found")
                else
                    call echo("Target was discovered: " + GetUnitName(target))
                endif
            endmethod
           
            private static method target_onDeathEvent takes nothing returns nothing
                local thistype this = get_targ(GetTriggerUnit())
               
                if this != 0 then
                    call target_search()
                    call target_attack()
                endif
            endmethod
           
            private static method hive_onDeathProxy takes nothing returns nothing
                local thistype this = GetTimerData(GetExpiredTimer())
                call destroy()
            endmethod
           
            private static method hive_onErupt takes nothing returns nothing
                local thistype this = hive_this
                set hive_this = 0
               
                set feedback_player = GetOwningPlayer(hive)
                call GroupEnumUnitsInRange(ENUM_GROUP, GetUnitX(hive), GetUnitY(hive), DATA(5, level), null)
                loop
                    set enum_unit = FirstOfGroup(ENUM_GROUP)
                    exitwhen enum_unit == null
                   
                    if UnitAlive(enum_unit) and IsUnitEnemy(enum_unit, feedback_player) then
                        if UnitDamageTarget(hive, enum_unit, DATA(7, level), true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_UNIVERSAL, null) then
                            call DestroyEffect(AddSpecialEffectTarget(MDL_FILE(1), enum_unit, "chest"))
                        endif
                    endif
                    call GroupRemoveUnit(ENUM_GROUP, enum_unit)
                endloop
            endmethod
           
            private method hive_onDeath takes nothing returns nothing
                call PauseTimer(timer)
                call TimerStart(timer, DATA(12, 0), false, function thistype.hive_onDeathProxy)
               
                set mode = 3
               
                if eventtype != 1 then
                    call SetUnitAnimation(hive, "death")
                endif
               
                if local_next == this then
                    call echo("Last reserved instance!")
                    call UnitRemoveAbility(unit, RAW_ID(2))
                debug else
                    call echo("Current instance: " + I2S(this))
                    call echo("Next instance: " + I2S(local_next) + "\n")
                    call echo("There are some instances left!")
                endif
               
                call detach()
               
                set hive_this = this
                call ForForce(bj_FORCE_PLAYER[0], function thistype.hive_onErupt)
                call spider_preDestroy()
            endmethod
           
            private method overmind_onTeleport takes nothing returns nothing
                local real rx = GetUnitX(unit)
                local real ry = GetUnitX(unit)
               
                local player p = GetOwningPlayer(unit)
               
                if this == 0 then
                    call echo("thistype.overmind_onTeleport: Invalid instance!")
                    return
                endif
               
                call SetWidgetLife(unit, GetWidgetLife(unit) + stored*DATA(4, level))
                call SetUnitState(unit, UNIT_STATE_MANA, GetUnitState(unit, UNIT_STATE_MANA) + stored*DATA(15, level))
               
                static if LIBRARY_TextTag then
                    call CreateTextTagBJ(p, rx, ry, 75, 0, 255, 255, "+" + I2S(R2I(stored*(DATA(4, level)))) + " health!\n+" + I2S(R2I(stored*(DATA(15, level)))) + " mana!")
                    set vj_lastCreatedTextTag.duration = 3.0
                    set vj_lastCreatedTextTag.fade = 2.25
                endif
               
                //  For boolean consistency
                set eventtype = 3
                if not (DATA(6, level) != 0) then
                    call echo("Removing timed life buffs")
                    call UnitRemoveBuffsEx(hive, true, true, false, false, true, false, false)              
                endif
               
                call DestroyEffect(AddSpecialEffect(MDL_FILE(3), rx, ry))
                call DestroyEffect(AddSpecialEffect(MDL_FILE(0), rx, ry))
               
                call SetUnitX(unit, GetUnitX(hive))
                call SetUnitY(unit, GetUnitX(hive))
           
                //  Unimportant to deallocate players (hear-say)
            endmethod
           
            private static method hive_onDeathEvent takes nothing returns nothing
                local thistype this = get_hive(GetTriggerUnit())
               
                if this != 0 then
                    if eventtype == 0 then
                        set eventtype = 1
                    endif
                    call hive_onDeath()
                endif
            endmethod
           
            private static method hive_onFeedback_loop takes nothing returns nothing
                local thistype this = GetTimerData(GetExpiredTimer())
               
                set mode_data = mode_data - DATA(2, level)
               
                if mode_data > 0. then
                    call target_attack()
                   
                    set feedback_player = GetOwningPlayer(hive)
                    call GroupEnumUnitsInRange(ENUM_GROUP, GetUnitX(hive), GetUnitY(hive), DATA(5, level), null)              
                    loop
                        set enum_unit = FirstOfGroup(ENUM_GROUP)
                        exitwhen enum_unit == null
                       
                        if UnitAlive(enum_unit) and IsUnitEnemy(enum_unit, feedback_player) then
                            if GetUnitState(enum_unit, UNIT_STATE_MAX_MANA) != 0 then
                                call DestroyEffect(AddSpecialEffectTarget(MDL_FILE(1), enum_unit, "chest"))
                               
                                call SetUnitState(enum_unit, UNIT_STATE_MANA, GetUnitState(enum_unit, UNIT_STATE_MANA) - DATA(3, level))
                                call UnitDamageTarget(hive, enum_unit, DATA(3, level), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null)
                               
                                set stored = stored + DATA(3, level)
                            endif
                        endif
                       
                        call GroupRemoveUnit(ENUM_GROUP, enum_unit)
                    endloop
                else
                    set eventtype = 2
                    call hive_onDeath()
                endif
            endmethod
           
            private static method hive_onDetectEnemy takes nothing returns nothing
                local thistype this = get_trig(GetTriggeringTrigger())
               
                if IsUnitEnemy(GetTriggerUnit(), GetOwningPlayer(hive)) then
                    if target == null then
                        set target = GetTriggerUnit()
                        call target_attack()
                    endif
                endif
            endmethod
           
            private static method spider_forGroupEx_enum takes nothing returns nothing
                local thistype this = spider_this
               
                set enum_unit = GetEnumUnit()
                set spider_group_count = spider_group_count + 1
               
                call SetUnitOwner(enum_unit, feedback_player, true)
                call SetUnitPosition(enum_unit, tx, ty)
                call SetUnitFacing(enum_unit, GetRandomReal(0, 360))
                       
                call PauseUnit(enum_unit, false)
                call ShowUnit(enum_unit, true)
                       
                call UnitRemoveAbility(enum_unit, 'Aloc')
                call UnitAddAbility(enum_unit, 'Aloc')
            endmethod
           
            private method spider_forGroupEx takes nothing returns integer
                set spider_this = this
                set spider_group_count = 0
               
                call ForGroup(spider_group, function thistype.spider_forGroupEx_enum)
               
                set enum_unit = null
                return spider_group_count
            endmethod
           
            private method hive_spider_init takes nothing returns nothing
                local integer int = R2I(DATA(8, level))
               
                set feedback_player = GetOwningPlayer(unit)
                if spider_group == null then
                    set spider_group = CreateGroup()
                endif
               
                set int = int - spider_forGroupEx()
               
                if int < 0 then
                    loop
                        set enum_unit = FirstOfGroup(spider_group)
                        exitwhen int >= 0
                       
                        call SetUnitOwner(enum_unit, Player(15), true)
                        call SetUnitX(enum_unit, 0)
                        call SetUnitY(enum_unit, 0)
                       
                        call PauseUnit(enum_unit, true)
                        call ShowUnit(enum_unit, false)
                       
                        call UnitRemoveAbility(enum_unit, 'Aloc')
                        call UnitAddAbility(enum_unit, 'Aloc')
                       
                        call GroupRemoveUnit(spider_group, enum_unit)
                        call GroupAddUnit(STORED_SPIDERS, enum_unit)
                       
                        set stored_spider_count = stored_spider_count + 1
                        set int = int + 1
                    endloop
                else
                    //  We check if there are any free spiders in the group.
                    loop
                        set enum_unit = FirstOfGroup(STORED_SPIDERS)
                        exitwhen enum_unit == null or int <= 0 or stored_spider_count <= 0
                       
                        call SetUnitOwner(enum_unit, feedback_player, true)
                        call SetUnitPosition(enum_unit, tx, ty)
                        call SetUnitFacing(enum_unit, GetRandomReal(0, 360))
                       
                        call PauseUnit(enum_unit, false)
                        call ShowUnit(enum_unit, true)
                       
                        call UnitRemoveAbility(enum_unit, 'Aloc')
                        call UnitAddAbility(enum_unit, 'Aloc')
                       
                        call GroupRemoveUnit(STORED_SPIDERS, enum_unit)
                        call GroupAddUnit(spider_group, enum_unit)
                       
                        set stored_spider_count = stored_spider_count - 1
                        set int = int - 1
                    endloop
                   
                    //  If there are none, proceed to the next loop
                    loop
                        exitwhen int <= 0
                       
                        set bj_lastCreatedUnit = CreateUnit(feedback_player, RAW_ID(1), tx, ty, GetRandomReal(0, 360))
                       
                        call SetUnitAcquireRange(bj_lastCreatedUnit, DATA(1, level))
                        call UnitAddAbility(bj_lastCreatedUnit, 'Aloc')
                        call Damage.add(bj_lastCreatedUnit)
                       
                        call GroupAddUnit(spider_group, bj_lastCreatedUnit)
                        set int = int - 1
                    endloop
                endif
               
                call echo("Number of spiders: " + I2S(CountUnitsInGroup(spider_group)))
            endmethod
           
            private method hive_addDetection takes nothing returns nothing
                set detector = CreateTrigger()
               
                call TriggerRegisterUnitInRange(detector, hive, DATA(1, level), null)
                call TriggerAddCondition(detector, function thistype.hive_onDetectEnemy)
            endmethod
           
            private method hive_addFeedback takes nothing returns nothing
                if not (DATA(6, level) != 0) then
                    call SetUnitInvulnerable(hive, false)
                    call UnitApplyTimedLife(hive, 'BTLF', mode_data)
                    call UnitPauseTimedLife(hive, false)
                endif
               
                call hive_addDetection()
                call hive_spider_init()
                call TimerStart(timer, DATA(2, level), true, function thistype.hive_onFeedback_loop)
            endmethod
           
            private static method hive_runList takes nothing returns nothing
                local thistype this = thistype(0).active_next
               
                if thistype(0).active_head == 0 then
                    call PauseTimer(ACTIVE_TIMER)
                    return
                endif
               
                loop
                    exitwhen this == 0
                    if mode == 1 then
                        call DestroyEffect(AddSpecialEffect(MDL_FILE(0), GetUnitX(hive), GetUnitY(hive)))
                       
                        static if REG_11_BOOL then
                            call SetUnitVertexColor(hive, 255, 255, 255, 255)
                           
                            set mode = 2
                            call hive_addFeedback()
                        else
                            set mode_data = mode_data + (255)*DATA(10, 0)/DATA(11, 0)
                           
                            if mode_data >= 255 then
                                call SetUnitVertexColor(hive, 255, 255, 255, 255)
                               
                                set mode = 2
                                set mode_data = DATA(0, level)
                               
                                call hive_addFeedback()
                            else
                                call SetUnitVertexColor(hive, 255, 255, 255, R2I(mode_data))
                            endif
                        endif
                    endif
                   
                    set this = active_next
                endloop
            endmethod
           
            private static method hive_spider_onDamage takes nothing returns nothing
                local thistype this = get_group(Damage.source)
                local real mode = ModuloReal(mode, 3.)
               
                if mode == 0 then
                    set mode = 3
                endif
               
                if this != 0 then
                    if mode == 1 then
                        set Damage.amount = DATA(14, level)*GetHeroStr(unit, true)
                    elseif mode == 2 then
                        set Damage.amount = DATA(14, level)*GetHeroAgi(unit, true)
                    elseif mode == 3 then
                        set Damage.amount = DATA(14, level)*GetHeroInt(unit, true)
                    endif
                endif
            endmethod
           
            //  Part one
            private static method hive_bufferAdd takes nothing returns nothing
                local thistype this = GetTimerData(GetExpiredTimer())
               
                call UnitAddAbility(hive, 'Aloc')
                call ReleaseTimer(GetExpiredTimer())
            endmethod
           
            private method hive_create takes nothing returns nothing
                if hive == null then
                    set hive = CreateUnit(GetOwningPlayer(unit), RAW_ID(0), tx, ty, 0)
                   
                    set mode = 1
                   
                    call SetUnitVertexColor(hive, 255, 255, 255, 0)
                   
                    if DATA(6, level) != 0 then
                        call TimerStart(NewTimerEx(this), 0., false, function thistype.hive_bufferAdd)
                    else
                        call SetUnitInvulnerable(hive, true)
                    endif
                else
                    call SetUnitAnimation(hive, "stand")
                    call QueueUnitAnimation(hive, "stand")
                    call SetUnitInvulnerable(hive, false)
                   
                    call SetUnitOwner(hive, GetOwningPlayer(unit), true)
                    call SetUnitPosition(hive, tx, ty)
                   
                    call PauseUnit(hive, false)
                    call ShowUnit(hive, true)
                   
                    if DATA(6, level) != 0 then
                        call UnitRemoveAbility(hive, 'Aloc')
                        call UnitAddAbility(hive, 'Aloc')
                    endif
                   
                    set mode = 1
               
                    call SetUnitVertexColor(hive, 255, 255, 255, 0)
                endif
               
                if GetLocalPlayer() == GetOwningPlayer(unit) then
                    call SelectUnit(hive, true)
                    call SelectUnit(hive, false)
                endif
               
                call active_push()
                set active_head = 1
               
                if thistype(0).active_head == 0 then
                    call TimerStart(ACTIVE_TIMER, DATA(10, 0), true, function thistype.hive_runList)
                endif
               
                set thistype(0).active_head = thistype(0).active_head + 1
            endmethod
           
            private static method prepare_hive_flag takes nothing returns nothing
                local thistype this = GetTimerData(GetExpiredTimer())
               
                call hive_create()
            endmethod
           
            private method prepare_hive takes nothing returns nothing
                set timer = NewTimerEx(this)
                call TimerStart(timer, real_GetDist(GetUnitX(unit), GetUnitY(unit), GetSpellTargetX(), GetSpellTargetY())/DATA(9, 0), false, function thistype.prepare_hive_flag)
            endmethod
           
            static method create takes unit u returns thistype
                local thistype this = get(u)
                local thistype that
               
                if this == 0 then
                    set this = allocate()
                    set unit = u
                   
                    set level = GetUnitAbilityLevel(u, SPELL_ID())
                    set head = 1
                   
                    call UnitAddAbility(u, RAW_ID(2))
                    call UnitMakeAbilityPermanent(u, true, RAW_ID(2))
                   
                    call push()
                    call local_insert(this)
                   
                    set tx = GetSpellTargetX()
                    set ty = GetSpellTargetY()
                   
                    call prepare_hive()
                    return this
                endif
                set that = allocate()
                set that.unit = unit
               
                set that.level = GetUnitAbilityLevel(unit, SPELL_ID())
                call that.local_insert(this)
               
                set that.tx = GetSpellTargetX()
                set that.ty = GetSpellTargetY()
               
                call UnitAddAbility(u, RAW_ID(2))
                call UnitMakeAbilityPermanent(u, true, RAW_ID(2))
                   
                call that.prepare_hive()
                return that
            endmethod
       
            static method teleport takes unit u, real x, real y returns nothing
                local thistype this = get(u)
                local thistype head = this
                local thistype nearest = head
               
                if this == 0 then
                    call echo("thistype.teleport: Instance of unit does not exist.")
                    call echo("thistype.teleport: Returning")
                    return
                endif
                           
                set this = local_next
                loop
                    exitwhen this == head
                   
                    if (real_GetDist(x, y, GetUnitX(hive), GetUnitY(hive)) <= real_GetDist(x, y, GetUnitX(nearest.hive), GetUnitY(nearest.hive))) and mode == 2 then
                        set nearest = this
                    endif
                   
                    set this = local_next
                endloop
               
                if nearest.mode != 2 then
                    call DisplayTextToPlayer(GetOwningPlayer(u), 0, 0, "|cffffcc00The hives are not available.|r")
                else
                    call nearest.overmind_onTeleport()
                endif
            endmethod
           
            //  Init method
            public static method init takes nothing returns nothing
                local trigger t = CreateTrigger()
               
                call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
                call TriggerAddCondition(t, function thistype.hive_onDeathEvent)
                call TriggerAddCondition(t, function thistype.target_onDeathEvent)
               
                set t = CreateTrigger()
               
                call Damage.registerModifierTrigger(t)
                call TriggerAddCondition(t, function thistype.hive_spider_onDamage)
                //  Located at part two
               
                set t = null
            endmethod
        endstruct
       
        private function OnSpellEvent takes nothing returns nothing
            if GetSpellAbilityId() == SPELL_ID() then
                call Data.create(GetTriggerUnit())
            elseif GetSpellAbilityId() == RAW_ID(2) then
                call Data.teleport(GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY())
            endif
        endfunction
       
        private function Init takes nothing returns nothing
            local trigger t = CreateTrigger()
           
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
            call TriggerAddCondition(t, function OnSpellEvent)
           
            call ForForce(bj_FORCE_PLAYER[0], function Data.init)
            set t = null
        endfunction

    endlibrary
     
     
    Last edited: Dec 29, 2017
  11. Exarch

    Exarch

    Joined:
    Mar 23, 2014
    Messages:
    157
    Resources:
    7
    Icons:
    7
    Resources:
    7
  12. KILLCIDE

    KILLCIDE

    Administrator

    Joined:
    Jul 22, 2015
    Messages:
    3,501
    Resources:
    20
    Models:
    2
    Icons:
    10
    Spells:
    7
    Tutorials:
    1
    Resources:
    20
    Our sticky yellow paint is done! I encountered so many WC3 bugs on this mechanic (note to self: never use raider ensnare). I was really hoping to make it a gradual slow, but I don't have that kind of time D: one more paint color to go!

    GIF
    WIP.gif


    Config
    • YPaint Config
      • Events
        • Map initialization
      • Conditions
      • Actions
        • -------- --------
        • -------- CONFIG START --------
        • -------- --------
        • -------- --------
        • -------- --------
        • -------- imported object editor data --------
        • Set YPaint_ABILITY_SLOW = Slow (Yellow Paint)
        • Set YPaint_BUFF_SLOW = Slow (Yellow Paint)
        • -------- ^ note: make sure ABILITY_SLOW is giving the corresponding BUFF_SLOW in Object Editor --------
        • Set YPaint_ABILITY_SNARE = Snare (Yellow Paint)
        • Set YPaint_BUFF_SNARE = Ensnared (Yellow Paint)
        • -------- ^ note: make sure ABILITY_SNARE is giving the corresponding BUFF_SNARE in Object Editor --------
        • -------- --------
        • -------- imported triggers --------
        • Set YPaint_TRIGGER_LOOP = YPaint Loop <gen>
        • Set YPaint_TRIGGER_APPLY_SLOW = YPaint Slow Index <gen>
        • Set YPaint_TRIGGER_LOOP_SLOW = YPaint Slow Loop <gen>
        • -------- --------
        • -------- how long (in seconds) the puddle will last --------
        • Set YPaint_PUDDLE_DURATION = 5.00
        • Set YPaint_PUDDLE_DURATION_PER_LVL = 0.00
        • -------- --------
        • -------- how close a unit must be to the puddle to be slowed --------
        • Set YPaint_AOE = 150.00
        • Set YPaint_AOE_PER_LEVEL = 0.00
        • -------- --------
        • -------- duration of the slow --------
        • Set YPaint_SLOW_DURATION = 5.00
        • Set YPaint_SLOW_DURATION_PER_LVL = 0.00
        • -------- --------
        • -------- special effect for puddle --------
        • Set YPaint_SFX_PUDDLE = PaintBombPuddle_Yellow.mdl
        • Set YPaint_SFX_PUDDLE_AP = origin
        • Set YPaint_SFX_PUDDLE_SIZE = 1.75
        • Set YPaint_SFX_PUDDLE_DEATH_TIMER = 0.25
        • -------- ^ how much time (in seconds) is needed for death sfx to play --------
        • -------- --------
        • -------- special effect applied to the target when they are slowed --------
        • Set YPaint_SFX_SLOW = Abilities\Spells\Human\slow\slowtarget.mdl
        • Set YPaint_SFX_SLOW_AP = origin
        • -------- --------
        • -------- other --------
        • Set YPaint_PERIODIC_TIMER = 0.03
        • -------- --------
        • -------- --------
        • -------- CONFIG END --------
        • -------- --------
        • Trigger - Add to YPaint_TRIGGER_LOOP the event (Time - Every YPaint_PERIODIC_TIMER seconds of game time)
        • Trigger - Add to YPaint_TRIGGER_LOOP_SLOW the event (Time - Every YPaint_PERIODIC_TIMER seconds of game time)
        • Set YPaint_KEY_ABILITY_LVL = 4
        • Set YPaint_KEY_DURATION = 5
        • Set YPaint_KEY_SFX = 6
        • -------- preload --------
        • Custom script: set udg_YPaint_DummyCaster = GetRecycledDummyAnyAngle(GetRectMaxX(bj_mapInitialPlayableArea), GetRectMaxY(bj_mapInitialPlayableArea), 0.00)
        • Special Effect - Create a special effect attached to the YPaint_SFX_PUDDLE_AP of YPaint_DummyCaster using YPaint_SFX_PUDDLE
        • Special Effect - Destroy (Last created special effect)
        • -------- turning dummy unit into dummy caster --------
        • Unit - Unpause YPaint_DummyCaster
        • Unit - Add YPaint_ABILITY_SLOW to YPaint_DummyCaster
        • Unit - Add YPaint_ABILITY_SNARE to YPaint_DummyCaster
        • -------- unpausing because dummy units are paused by DummyRecycler --------
        • Custom script: call UnitRemoveAbility(udg_YPaint_DummyCaster, 'Amov')
        • -------- math calculations --------
        • Set YPaint_SFX_PUDDLE_SIZE = (YPaint_SFX_PUDDLE_SIZE x 100.00)


    Index
    • YPaint Index
      • Events
      • Conditions
      • Actions
        • -------- YPaint Index --------
        • -------- this trigger will create a new instance for the yellow paint mechanic --------
        • -------- --------
        • -------- members --------
        • -------- Caster[] = unit who casted PBomb_ABILITY --------
        • -------- Owner[] = player who owns Caster[] that threw the paint bucket --------
        • -------- AbilityLvl[] = level of PBomb_ABILITY when the caster initially casted the ability --------
        • -------- CurrentColor[] - the color the caster had selected when they casted PBomb_ABILITY --------
        • -------- Counter[] = duration of puddle --------
        • -------- PuddleX[] - x coordinate for the puddle --------
        • -------- PuddleY[] - y coordinate for the puddle --------
        • -------- --------
        • -------- --------
        • Set YPaint_SpellCount = (YPaint_SpellCount + 1)
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • YPaint_SpellCount Equal to 1
          • Then - Actions
            • Trigger - Turn on YPaint_TRIGGER_LOOP
          • Else - Actions
            • -------- do nothing --------
        • -------- --------
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • YPaint_RecycledSize Equal to 0
          • Then - Actions
            • Set YPaint_MaxIndex = (YPaint_MaxIndex + 1)
            • Set YPaint_SpellId = YPaint_MaxIndex
          • Else - Actions
            • Set YPaint_RecycledSize = (YPaint_RecycledSize - 1)
            • Set YPaint_SpellId = YPaint_RecycledStack[YPaint_RecycledSize]
        • Set YPaint_NodeNext[YPaint_SpellId] = 0
        • Set YPaint_NodePrev[YPaint_SpellId] = YPaint_NodePrev[0]
        • Set YPaint_NodeNext[YPaint_NodePrev[0]] = YPaint_SpellId
        • Set YPaint_NodePrev[0] = YPaint_SpellId
        • -------- --------
        • Set YPaint_Caster[YPaint_SpellId] = PBomb_Caster[PBomb_SpellId]
        • Set YPaint_Owner[YPaint_SpellId] = PBomb_Owner[PBomb_SpellId]
        • Set YPaint_AbilityLvl[YPaint_SpellId] = PBomb_AbilityLvl[PBomb_SpellId]
        • Set YPaint_CurrentColor[YPaint_SpellId] = PBomb_CurrentColor[PBomb_SpellId]
        • -------- --------
        • Set YPaint_TempReal = (Real(YPaint_AbilityLvl[YPaint_SpellId]))
        • Set YPaint_Counter[YPaint_SpellId] = (YPaint_PUDDLE_DURATION + (YPaint_PUDDLE_DURATION_PER_LVL x YPaint_TempReal))
        • Set YPaint_Radius[YPaint_SpellId] = (YPaint_AOE + (YPaint_AOE_PER_LEVEL x YPaint_TempReal))
        • -------- --------
        • Custom script: set udg_YPaint_PuddleX[udg_YPaint_SpellId] = GetUnitX(udg_PBomb_MissileUnit[udg_PBomb_SpellId])
        • Custom script: set udg_YPaint_PuddleY[udg_YPaint_SpellId] = GetUnitY(udg_PBomb_MissileUnit[udg_PBomb_SpellId])
        • Custom script: set udg_YPaint_PuddleUnit[udg_YPaint_SpellId] = GetRecycledDummyAnyAngle(udg_YPaint_PuddleX[udg_YPaint_SpellId], udg_YPaint_PuddleY[udg_YPaint_SpellId], 0.00)
        • Animation - Change YPaint_PuddleUnit[YPaint_SpellId]'s size to (YPaint_SFX_PUDDLE_SIZE%, 100.00%, 100.00%) of its original size
        • Special Effect - Create a special effect attached to the YPaint_SFX_PUDDLE_AP of YPaint_PuddleUnit[YPaint_SpellId] using YPaint_SFX_PUDDLE
        • Set YPaint_PuddleSfx[YPaint_SpellId] = (Last created special effect)


    Loop
    • YPaint Loop
      • Events
      • Conditions
      • Actions
        • -------- YPaint Loop --------
        • -------- this trigger will periodically check if there are units within the radius of the puddle --------
        • -------- if there is an enemy unit within the puddle, the dummy caster will apply the slow effect on them --------
        • -------- if the enemy unit is already affected by the slow or snare, the dummy caster will do nothing --------
        • -------- --------
        • -------- members --------
        • -------- Caster[] = unit who casted PBomb_ABILITY --------
        • -------- Owner[] = player who owns Caster[] that threw the paint bucket --------
        • -------- AbilityLvl[] = level of PBomb_ABILITY when the caster initially casted the ability --------
        • -------- CurrentColor[] - the color the caster had selected when they casted PBomb_ABILITY --------
        • -------- Counter[] = duration of puddle --------
        • -------- PuddleX[] - x coordinate for the puddle --------
        • -------- PuddleY[] - y coordinate for the puddle --------
        • -------- --------
        • -------- --------
        • Set YPaint_SpellId = 0
        • For each (Integer YPaint_LoopInt) from 1 to YPaint_SpellCount, do (Actions)
          • Loop - Actions
            • Set YPaint_SpellId = YPaint_NodeNext[YPaint_SpellId]
            • -------- --------
            • -------- checking if the puddle reached the end of its life span --------
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • YPaint_Counter[YPaint_SpellId] Less than or equal to 0.00
              • Then - Actions
                • -------- puddle has reached the end of its life span; deallocate instance --------
                • -------- --------
                • -------- decreasing number of active puddles for this color --------
                • Custom script: set udg_SPaint_UnitId = GetHandleId(udg_YPaint_Caster[udg_YPaint_SpellId])
                • Hashtable - Save ((Load PBomb_KEY_ACTIVE_COLOR_COUNT[YPaint_CurrentColor[YPaint_SpellId]] of SPaint_UnitId from PBomb_Hash) - 1) as PBomb_KEY_ACTIVE_COLOR_COUNT[YPaint_CurrentColor[YPaint_SpellId]] of SPaint_UnitId in PBomb_Hash
                • -------- --------
                • Special Effect - Destroy YPaint_PuddleSfx[YPaint_SpellId]
                • Custom script: call DummyAddRecycleTimer(udg_YPaint_PuddleUnit[udg_YPaint_SpellId], udg_YPaint_SFX_PUDDLE_DEATH_TIMER)
                • Set YPaint_RecycledStack[YPaint_RecycledSize] = YPaint_SpellId
                • Set YPaint_RecycledSize = (YPaint_RecycledSize + 1)
                • Set YPaint_NodeNext[YPaint_NodePrev[YPaint_SpellId]] = YPaint_NodeNext[YPaint_SpellId]
                • Set YPaint_NodePrev[YPaint_NodeNext[YPaint_SpellId]] = YPaint_NodePrev[YPaint_SpellId]
                • -------- --------
                • Set YPaint_SpellCount = (YPaint_SpellCount - 1)
                • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • YPaint_SpellCount Equal to 0
                  • Then - Actions
                    • Trigger - Turn off YPaint_TRIGGER_LOOP
                  • Else - Actions
                    • -------- do nothing --------
              • Else - Actions
                • -------- puddle has not reached the end of its life span; continue slowing nearby enemy units --------
                • Set YPaint_Counter[YPaint_SpellId] = (YPaint_Counter[YPaint_SpellId] - YPaint_PERIODIC_TIMER)
                • -------- --------
                • Custom script: call SetUnitX(udg_YPaint_DummyCaster, udg_YPaint_PuddleX[udg_YPaint_SpellId])
                • Custom script: call SetUnitY(udg_YPaint_DummyCaster, udg_YPaint_PuddleY[udg_YPaint_SpellId])
                • -------- using GroupEnumUnitsInRange because GetUnitsInRangeOfLoc has a reference handle leak --------
                • Custom script: call GroupEnumUnitsInRange(udg_PBomb_InRangeGroup, udg_YPaint_PuddleX[udg_YPaint_SpellId], udg_YPaint_PuddleY[udg_YPaint_SpellId], udg_YPaint_Radius[udg_YPaint_SpellId], null)
                • Unit Group - Pick every unit in PBomb_InRangeGroup and do (Actions)
                  • Loop - Actions
                    • Set YPaint_TempUnit = (Picked unit)
                    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                      • If - Conditions
                        • (YPaint_TempUnit is A structure) Equal to False
                        • (YPaint_TempUnit is A flying unit) Equal to False
                        • (YPaint_TempUnit is Magic Immune) Equal to False
                        • (YPaint_TempUnit is alive) Equal to True
                        • (YPaint_TempUnit belongs to an enemy of YPaint_Owner[YPaint_SpellId]) Equal to True
                        • (YPaint_TempUnit has buff YPaint_BUFF_SLOW) Equal to False
                        • (YPaint_TempUnit has buff YPaint_BUFF_SNARE) Equal to False
                      • Then - Actions
                        • Trigger - Run YPaint_TRIGGER_APPLY_SLOW (ignoring conditions)
                      • Else - Actions
                        • -------- do nothing --------
                    • Unit Group - Remove YPaint_TempUnit from PBomb_InRangeGroup


    Slow Index
    • YPaint Slow Index
      • Events
      • Conditions
      • Actions
        • -------- YPaint Slow Index --------
        • -------- this trigger will create an instance that slows the affected unit --------
        • -------- --------
        • -------- --------
        • Custom script: set udg_YPaint_UnitId = GetHandleId(udg_YPaint_TempUnit)
        • -------- --------
        • Unit Group - Add YPaint_TempUnit to YPaint_SlowedGroup
        • Set YPaint_GroupCount = (YPaint_GroupCount + 1)
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • YPaint_GroupCount Equal to 1
          • Then - Actions
            • Trigger - Turn on YPaint_TRIGGER_LOOP_SLOW
          • Else - Actions
            • -------- do nothing --------
        • -------- --------
        • Set YPaint_SlowCounter = (YPaint_SLOW_DURATION + (YPaint_SLOW_DURATION_PER_LVL x (Real(YPaint_AbilityLvl[YPaint_SpellId]))))
        • Unit - Order YPaint_DummyCaster to Human Sorceress - Slow YPaint_TempUnit
        • Special Effect - Create a special effect attached to the YPaint_SFX_SLOW_AP of YPaint_TempUnit using YPaint_SFX_SLOW
        • -------- --------
        • Hashtable - Save YPaint_AbilityLvl[YPaint_SpellId] as YPaint_KEY_ABILITY_LVL of YPaint_UnitId in PBomb_Hash
        • Hashtable - Save YPaint_SlowCounter as YPaint_KEY_DURATION of YPaint_UnitId in PBomb_Hash
        • Hashtable - Save Handle Of(Last created special effect) as YPaint_KEY_SFX of YPaint_UnitId in PBomb_Hash


    Slow Loop
    • YPaint Slow Loop
      • Events
      • Conditions
      • Actions
        • -------- YPaint Slow Loop --------
        • -------- this trigger will keep track of the duration of the slow on affected units --------
        • -------- if the unit still has the buff at the end of the duration, they will be snared --------
        • -------- --------
        • -------- --------
        • Unit Group - Pick every unit in YPaint_SlowedGroup and do (Actions)
          • Loop - Actions
            • Set YPaint_Target = (Picked unit)
            • Custom script: set udg_YPaint_UnitId = GetHandleId(udg_YPaint_Target)
            • -------- --------
            • Set YPaint_SlowCounter = ((Load YPaint_KEY_DURATION of YPaint_UnitId from PBomb_Hash) - YPaint_PERIODIC_TIMER)
            • -------- checking if the target loss the buff or if the duration is over --------
            • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
              • If - Conditions
                • Or - Any (Conditions) are true
                  • Conditions
                    • (YPaint_Target is dead) Equal to True
                    • (YPaint_Target has buff YPaint_BUFF_SLOW) Equal to False
                    • YPaint_SlowCounter Less than or equal to 0.00
              • Then - Actions
                • -------- --------
                • -------- checking if target still has buff --------
                • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • (YPaint_Target has buff YPaint_BUFF_SLOW) Equal to True
                  • Then - Actions
                    • -------- target still had buff at the end of the duration; manually remove slow and snare the target --------
                    • Unit - Remove YPaint_BUFF_SLOW buff from YPaint_Target
                    • -------- --------
                    • Custom script: call SetUnitX(udg_YPaint_DummyCaster, GetUnitX(udg_YPaint_Target))
                    • Custom script: call SetUnitY(udg_YPaint_DummyCaster, GetUnitY(udg_YPaint_Target))
                    • Unit - Set level of YPaint_ABILITY_SNARE for YPaint_DummyCaster to (Load YPaint_KEY_ABILITY_LVL of YPaint_UnitId from PBomb_Hash)
                    • Unit - Order YPaint_DummyCaster to Night Elf Keeper Of The Grove - Entangling Roots YPaint_Target
                  • Else - Actions
                    • -------- target loss the debuff; do nothing --------
                • -------- --------
                • Special Effect - Destroy (Load YPaint_KEY_SFX of YPaint_UnitId in PBomb_Hash)
                • -------- manually removing child keys because other child keys still might be in use --------
                • Custom script: call RemoveSavedInteger(udg_PBomb_Hash, udg_YPaint_UnitId, udg_YPaint_KEY_ABILITY_LVL)
                • Custom script: call RemoveSavedReal(udg_PBomb_Hash, udg_YPaint_UnitId, udg_YPaint_KEY_DURATION)
                • Custom script: call RemoveSavedHandle(udg_PBomb_Hash, udg_YPaint_UnitId, udg_YPaint_KEY_SFX)
                • -------- --------
                • Unit Group - Remove YPaint_Target from YPaint_SlowedGroup
                • Set YPaint_GroupCount = (YPaint_GroupCount - 1)
                • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                  • If - Conditions
                    • YPaint_GroupCount Equal to 0
                  • Then - Actions
                    • Trigger - Turn off YPaint_TRIGGER_LOOP_SLOW
                  • Else - Actions
                    • -------- do nothing --------
              • Else - Actions
                • -------- target still has the debuff with time left; save duration left --------
                • Hashtable - Save YPaint_SlowCounter as YPaint_KEY_DURATION of YPaint_UnitId in PBomb_Hash


    Side note: @Cokemonkey11 is going to hate me after this contest. Give me a fair review and I promise to consider Wurst next year!

    Capture.PNG
     
  13. Flux

    Flux

    Joined:
    Feb 6, 2014
    Messages:
    2,333
    Resources:
    28
    Maps:
    1
    Spells:
    19
    Tutorials:
    2
    JASS:
    6
    Resources:
    28
    As far as I know, entries whether written in GUI, JASS, vJASS or Wurst are all judged equally and does not affect the scoring so I think Cokemonkey will give you a fair review.
     
  14. ~Nightmare

    ~Nightmare

    Joined:
    Jan 25, 2011
    Messages:
    2,106
    Resources:
    144
    Models:
    2
    Icons:
    111
    Packs:
    5
    Skins:
    26
    Resources:
    144
    Need to rush rush rush, wasn't able to contribute largely this holiday season, sadly.
     
  15. Astaroth Zion

    Astaroth Zion

    Joined:
    Feb 13, 2011
    Messages:
    360
    Resources:
    26
    Models:
    25
    Packs:
    1
    Resources:
    26
    Team: JustAZbound

    Resource: Model Wip_1

    Stuff Done: most mesh and ingame textures

    Stuff to do: (a lot), textures for turret, engine and cockpit, rigging, animating, adding effects, finishing magos details.
    @IcemanBo
    GeneralFrank_Model_wip1.JPG GeneralFrank_Model_wip2.JPG
     
  16. Kyrbi0

    Kyrbi0

    Joined:
    Jul 29, 2008
    Messages:
    7,906
    Resources:
    1
    Models:
    1
    Resources:
    1
    @IcemanBo @Murlocologist

    I was talking with @KILLCIDE in the Discord, and it was brought to my attention that there is some small ambiguity in the Deadline Time as dictated by the first post in the Contest Thread.

    Personally, as a Host, I have found it best to be absolutely, expressly specific, so as to avoid any frustrating confusion (for entrants yes, but also for the Host himself; having to deal with people misunderstanding. ;P)

    I move to clarify the deadline as follows:

    This way it is unequivocal which day, date, month & year are being talked about, and most importantly both the time frame & the time zone. (if we use/assume midnight (generally considered the 'end of the day' but technically the beginning of the next), people might assume the 31st is part of it. Or move back from 12 & be a minute late, etc).

    ~~~

    Now, that being said, let me also put in my voice for a slight extension (lol); perhaps even if only a few days (say Tuesday, January 2nd, 2018 @ 11:59:59PM (GMT 0) or somesuch). While it's true it's the holidays and many people have work/school off, it's also true that many people are spending those holidays away/visiting said family, and modding time is not exactly at it's highest.
    Just my $0.02
     
  17. KILLCIDE

    KILLCIDE

    Administrator

    Joined:
    Jul 22, 2015
    Messages:
    3,501
    Resources:
    20
    Models:
    2
    Icons:
    10
    Spells:
    7
    Tutorials:
    1
    Resources:
    20
    For the record, I didn't start on my entry until the 16th of December because I had school, so I had a lot less time. With that in mind, I agree with the extension. I start school again on the 2nd, but the extra few days will allow me to debug and review my code more thoroughly.
     
  18. Paillan

    Paillan

    Map Reviewer

    Joined:
    Jan 22, 2011
    Messages:
    3,026
    Resources:
    2
    Models:
    2
    Resources:
    2
    Giv more time plox.
    Mostly because of time zone but also because of the bad placement of this contest (before Christmas and new year)
     
  19. Astaroth Zion

    Astaroth Zion

    Joined:
    Feb 13, 2011
    Messages:
    360
    Resources:
    26
    Models:
    25
    Packs:
    1
    Resources:
    26
    I am thankful of the the first deadline extension, however, due to family trips and commitments I will only be able to use 1 of the 8 days added to the deadline. Can we have a second extension that gives use one more weekend outside holidays?

    EDIT: ps I am of those who only gets 1 week vacation off work.
     
  20. MyPad

    MyPad

    Spell Reviewer

    Joined:
    May 9, 2014
    Messages:
    1,324
    Resources:
    7
    Models:
    1
    Icons:
    2
    Spells:
    3
    JASS:
    1
    Resources:
    7
    @Kyrbi0

    Perhaps, what you said earlier (Byzantium style suggested by Zwiebelchen except not reverse) may apply here.

    So what was the extended time and date? December 30, 2017, 7:59:59 A.M. GMT +08:00 or 7:59:59 P.M. GMT +08:00?
     
Thread Status:
Not open for further replies.