Static Fence v.01

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
This spell is made by Maker and requested by me. But when i tested , it's very cool and i think everyone deserves to have this spell so i share it. I also want to learn to become a great spell creator like Maker so i'll try to answer your question if i can't than i'll pass it to Maker.. Credit goes to Maker as the creator.

Description:
The caster creates 2 ball of lightning in front of him. Theres a range between the ball and connected with a magical link. Then the 2 ball will go foward and anyone who touch the link will be knockbacked and damaged. At the end, the ball will explode and damage nearby enemy.

Tutorial, How to Import, etc is already in the map.

I think it leakless but free to comment!

Trigger :
  • SF Init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set SF_Hash = (Last created hashtable)
      • -------- -------------------------------------------------- --------
      • -------- The ability --------
      • -------- -------------------------------------------------- --------
      • Set SF_Ability = Static Fence
      • -------- -------------------------------------------------- --------
      • -------- Dummy unit type --------
      • -------- -------------------------------------------------- --------
      • Set SF_Dummy_Type = SF Dummy
      • -------- -------------------------------------------------- --------
      • -------- Dummy item for collision checking --------
      • -------- -------------------------------------------------- --------
      • Set SF_Item_Type = Collision Item
      • Custom script: set udg_SF_Item = CreateItem( udg_SF_Item_Type , 0 , 0 )
      • Item - Hide SF_Item
      • -------- -------------------------------------------------- --------
      • -------- Lightning's type --------
      • -------- -------------------------------------------------- --------
      • Set SF_Lightning = DRAM
      • -------- -------------------------------------------------- --------
      • -------- Effect when damage is taken from the fence --------
      • Set SF_Effects[0] = Abilities\Weapons\FaerieDragonMissile\FaerieDragonMissile.mdl
      • -------- Effect when damage is taken from AoE explosion --------
      • Set SF_Effects[1] = Abilities\Spells\Orc\Purge\PurgeBuffTarget.mdl
      • -------- Knockback effect attached to origin --------
      • Set SF_Effects[2] = Abilities\Spells\Other\Tornado\Tornado_Target.mdl
      • -------- -------------------------------------------------- --------
      • -------- Ball offset, how far away to left and right of the caster will the balls go --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[0] = 150.00
      • -------- -------------------------------------------------- --------
      • -------- Ball max distance, how far the balls travel --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[1] = 700.00
      • -------- -------------------------------------------------- --------
      • -------- Ball average flying height --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[2] = 50.00
      • -------- -------------------------------------------------- --------
      • -------- Initial visibility of the balls and lightning --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[3] = 0.00
      • -------- -------------------------------------------------- --------
      • -------- Ball speed --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[4] = 15.00
      • -------- -------------------------------------------------- --------
      • -------- Damage, base --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[5] = 50.00
      • -------- -------------------------------------------------- --------
      • -------- Damage, bonus per ability level --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[6] = 25.00
      • -------- -------------------------------------------------- --------
      • -------- Ball speed sideways --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[7] = 5.00
      • -------- -------------------------------------------------- --------
      • -------- Lightning width / 2 --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[8] = 16.00
      • -------- -------------------------------------------------- --------
      • -------- Explosion AoE --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[9] = 150.00
      • -------- -------------------------------------------------- --------
      • -------- AoE Damage, base --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[10] = 50.00
      • -------- -------------------------------------------------- --------
      • -------- AoE damage, bonus per ability level --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[11] = 25.00
      • -------- -------------------------------------------------- --------
      • -------- Knocback minimum speed --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[12] = 3.00
      • -------- -------------------------------------------------- --------
      • -------- Knocback initial speed --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[13] = 30.00
      • -------- -------------------------------------------------- --------
      • -------- Knocback deceleration --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[14] = 1.10
      • -------- -------------------------------------------------- --------
      • -------- Flying height change speed --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[15] = 8.00
      • -------- -------------------------------------------------- --------
      • -------- Rectangle extra offset --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[16] = 32.00
  • SF Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to SF_Ability
    • Actions
      • Set u1 = (Triggering unit)
      • Set p1 = (Position of u1)
      • Set r1 = (Facing of u1)
      • Set i1 = ((Level of SF_Ability for u1) - 1)
      • Set r2 = (100.00 - (SF_Reals[3] x 100.00))
      • -------- -------------------------------------------------- --------
      • Set r3 = (Random real number between 0.00 and 360.00)
      • Unit - Create 1 SF_Dummy_Type for Neutral Passive at p1 facing r1 degrees
      • Set u2 = (Last created unit)
      • Custom script: set udg_ID = GetHandleId(udg_u2)
      • Unit Group - Add u2 to SF_Balls
      • Unit - Make u2 Explode on death
      • Animation - Change u2 flying height to SF_Reals[2] at 0.00
      • Animation - Change u2 flying height to (SF_Reals[2] + ((SF_Reals[2] / 2.00) x (Sin(r3)))) at 600.00
      • Animation - Change u2's vertex coloring to (100.00%, 100.00%, 100.00%) with r2% transparency
      • Custom script: call UnitAddAbility(udg_u2 , 'Arav' )
      • Hashtable - Save r3 as (Key phase1) of ID in SF_Hash
      • -------- -------------------------------------------------- --------
      • Set r3 = (Random real number between 0.00 and 360.00)
      • Unit - Create 1 SF_Dummy_Type for Neutral Passive at p1 facing r1 degrees
      • Set u2 = (Last created unit)
      • Unit - Make u2 Explode on death
      • Animation - Change u2 flying height to SF_Reals[2] at 0.00
      • Animation - Change u2 flying height to (SF_Reals[2] + ((SF_Reals[2] / 2.00) x (Sin(r3)))) at 600.00
      • Animation - Change u2's vertex coloring to (100.00%, 100.00%, 100.00%) with r2% transparency
      • Custom script: call UnitAddAbility(udg_u2 , 'Arav' )
      • Hashtable - Save r3 as (Key phase2) of ID in SF_Hash
      • -------- -------------------------------------------------- --------
      • Custom script: set bj_lastCreatedLightning = AddLightningEx( udg_SF_Lightning , true , GetLocationX(udg_p1) , GetLocationY(udg_p1) , GetLocationZ(udg_p1) + udg_SF_Reals[2] , GetLocationX(udg_p1) , GetLocationY(udg_p1) , GetLocationZ(udg_p1) + udg_SF_Reals[2])
      • Lightning - Change color of (Last created lightning effect) to (1.00 1.00 1.00) with SF_Reals[3] alpha
      • -------- -------------------------------------------------- --------
      • Custom script: set udg_g1 = CreateGroup()
      • -------- -------------------------------------------------- --------
      • Hashtable - Save Handle Ofg1 as (Key group) of ID in SF_Hash
      • Hashtable - Save Handle Ofp1 as (Key center) of ID in SF_Hash
      • Hashtable - Save Handle Ofu1 as (Key caster) of ID in SF_Hash
      • Hashtable - Save Handle Of(Last created unit) as (Key other) of ID in SF_Hash
      • Hashtable - Save Handle Of(Last created lightning effect) as (Key lightning) of ID in SF_Hash
      • Hashtable - Save r1 as (Key angle) of ID in SF_Hash
      • Hashtable - Save r2 as (Key transparency) of ID in SF_Hash
      • Hashtable - Save (r2 / (90.00 / SF_Reals[4])) as (Key visibilitySpeed) of ID in SF_Hash
      • Hashtable - Save 0.00 as (Key sideOffset) of ID in SF_Hash
      • Hashtable - Save (r1 + 90.00) as (Key angleSide) of ID in SF_Hash
      • Hashtable - Save (SF_Reals[5] + (SF_Reals[6] x (Real(i1)))) as (Key damage) of ID in SF_Hash
      • Hashtable - Save (SF_Reals[10] + (SF_Reals[11] x (Real(i1)))) as (Key damageAoE) of ID in SF_Hash
      • -------- -------------------------------------------------- --------
      • Trigger - Turn on SF Loop <gen>
      • -------- -------------------------------------------------- --------
  • SF Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in SF_Balls and do (Actions)
        • Loop - Actions
          • Set u1 = (Picked unit)
          • Set ID = (Key (Picked unit))
          • Set u2 = (Load (Key caster) of ID in SF_Hash)
          • Set u3 = (Load (Key other) of ID in SF_Hash)
          • Set l1 = (Load (Key lightning) of ID in SF_Hash)
          • Set i1 = (Load (Key phase) of ID from SF_Hash)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • i1 Not equal to 2
              • (u2 is alive) Equal to True
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • i1 Equal to 0
                • Then - Actions
                  • Set r1 = (Load (Key angleSide) of ID from SF_Hash)
                  • Set r2 = (r1 - 180.00)
                  • Set r3 = ((Load (Key sideOffset) of ID from SF_Hash) + SF_Reals[7])
                  • Set p1 = (Load (Key center) of ID in SF_Hash)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • r3 Greater than or equal to SF_Reals[0]
                    • Then - Actions
                      • Set r3 = SF_Reals[0]
                      • Set p2 = (p1 offset by r3 towards r1 degrees)
                      • Set p3 = (p1 offset by r3 towards r2 degrees)
                      • Unit - Move u1 instantly to p2
                      • Unit - Move u3 instantly to p3
                      • Animation - Change u1's vertex coloring to (100.00%, 100.00%, 100.00%) with 0.00% transparency
                      • Animation - Change u3's vertex coloring to (100.00%, 100.00%, 100.00%) with 0.00% transparency
                      • Lightning - Change color of l1 to (1.00 1.00 1.00) with 1.00 alpha
                      • Custom script: call RemoveLocation(udg_p1)
                      • Hashtable - Save 1 as (Key phase) of ID in SF_Hash
                    • Else - Actions
                      • Set p2 = (p1 offset by r3 towards r1 degrees)
                      • Set p3 = (p1 offset by r3 towards r2 degrees)
                      • Unit - Move u1 instantly to p2
                      • Unit - Move u3 instantly to p3
                      • Set r4 = ((Load (Key transparency) of ID from SF_Hash) - (Load (Key visibilitySpeed) of ID from SF_Hash))
                      • Animation - Change u1's vertex coloring to (100.00%, 100.00%, 100.00%) with r4% transparency
                      • Animation - Change u3's vertex coloring to (100.00%, 100.00%, 100.00%) with r4% transparency
                      • Lightning - Change color of l1 to (1.00 1.00 1.00) with (1.00 - (r4 / 100.00)) alpha
                      • Hashtable - Save r3 as (Key sideOffset) of ID in SF_Hash
                      • Hashtable - Save r4 as (Key transparency) of ID in SF_Hash
                  • Custom script: call MoveLightningEx( udg_l1 , true , GetLocationX(udg_p2) , GetLocationY(udg_p2) , GetLocationZ(udg_p2) + GetUnitFlyHeight(udg_u1) , GetLocationX(udg_p3) , GetLocationY(udg_p3) , GetLocationZ(udg_p3) + GetUnitFlyHeight(udg_u3) )
                  • Custom script: call RemoveLocation(udg_p2)
                  • Custom script: call RemoveLocation(udg_p3)
                • Else - Actions
                  • Set r1 = (Load (Key damage) of ID from SF_Hash)
                  • Set r2 = (Load (Key angle) of ID from SF_Hash)
                  • Set p1 = (Position of u1)
                  • Set p2 = (p1 offset by SF_Reals[4] towards r2 degrees)
                  • Set p3 = (p2 offset by (2.00 x SF_Reals[0]) towards (r2 - 90.00) degrees)
                  • -------- -------------------------------------------------- --------
                  • Unit - Move u1 instantly to p2
                  • Unit - Move u3 instantly to p3
                  • -------- -------------------------------------------------- --------
                  • Set r3 = (Load (Key phase1) of ID from SF_Hash)
                  • Animation - Change u1 flying height to (SF_Reals[2] + ((SF_Reals[2] / 2.00) x (Sin(r3)))) at 0.00
                  • Hashtable - Save (r3 + SF_Reals[15]) as (Key phase1) of ID in SF_Hash
                  • Set r3 = (Load (Key phase2) of ID from SF_Hash)
                  • Animation - Change u3 flying height to (SF_Reals[2] + ((SF_Reals[2] / 2.00) x (Sin(r3)))) at 0.00
                  • Hashtable - Save (r3 + SF_Reals[15]) as (Key phase2) of ID in SF_Hash
                  • -------- -------------------------------------------------- --------
                  • Custom script: call MoveLightningEx( udg_l1 , true , GetLocationX(udg_p2) , GetLocationY(udg_p2) , GetLocationZ(udg_p2) + GetUnitFlyHeight(udg_u1) , GetLocationX(udg_p3) , GetLocationY(udg_p3) , GetLocationZ(udg_p3) + GetUnitFlyHeight(udg_u3) )
                  • -------- -------------------------------------------------- --------
                  • Custom script: set udg_r2 = udg_r2 * bj_DEGTORAD
                  • Custom script: set udg_r3 = GetUnitX(udg_u1) + udg_SF_Reals[16] * Cos(udg_r2+bj_PI/2)
                  • Custom script: set udg_r4 = GetUnitY(udg_u1) + udg_SF_Reals[16] * Sin(udg_r2+bj_PI/2)
                  • -------- Lower left corner --------
                  • Custom script: set udg_r5 = udg_r3 + udg_SF_Reals[8] * Cos(udg_r2-bj_PI)
                  • Custom script: set udg_r6 = udg_r4 + udg_SF_Reals[8] * Sin(udg_r2-bj_PI)
                  • -------- Upper left corner --------
                  • Custom script: set udg_r7 = udg_r3 + udg_SF_Reals[8] * Cos(udg_r2)
                  • Custom script: set udg_r8 = udg_r4 + udg_SF_Reals[8] * Sin(udg_r2)
                  • -------- Lower right corner --------
                  • Custom script: set udg_r9 = udg_r5 + 2 * (udg_SF_Reals[0] + udg_SF_Reals[16]) * Cos(udg_r2-bj_PI/2)
                  • Custom script: set udg_r10 = udg_r6 + 2 * (udg_SF_Reals[0] + udg_SF_Reals[16]) * Sin(udg_r2-bj_PI/2)
                  • -------- -------------------------------------------------- --------
                  • Custom script: call RemoveLocation(udg_p1)
                  • -------- -------------------------------------------------- --------
                  • Set player = (Owner of u2)
                  • Set g1 = (Load (Key group) of ID in SF_Hash)
                  • Custom script: set bj_wantDestroyGroup = true
                  • Unit Group - Pick every unit in (Units within (2.50 x SF_Reals[0]) of p2 matching ((((Matching unit) is alive) Equal to True) and ((((Matching unit) belongs to an enemy of player) Equal to True) and (((Matching unit) is A ground unit) Equal to True)))) and do (Actions)
                    • Loop - Actions
                      • Set u4 = (Picked unit)
                      • Custom script: set udg_SF_Boolean = IsPointInRect( GetUnitX(udg_u4) , GetUnitY(udg_u4) , udg_r5 , udg_r6 , udg_r7 , udg_r8 , udg_r9 , udg_r10 )
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (u4 is in g1) Equal to False
                          • SF_Boolean Equal to True
                        • Then - Actions
                          • Unit Group - Add u4 to g1
                          • Custom script: call UnitDamageTarget( udg_u2 , udg_u4 , udg_r1 , false , true , ATTACK_TYPE_NORMAL , DAMAGE_TYPE_NORMAL , WEAPON_TYPE_WHOKNOWS )
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • (u4 is A structure) Equal to False
                            • Then - Actions
                              • Unit Group - Add u4 to SF_KB
                              • Special Effect - Create a special effect attached to the origin of u4 using SF_Effects[2]
                              • Hashtable - Save Handle Of(Last created special effect) as (Key e) of (Key (Picked unit)) in SF_Hash
                              • Hashtable - Save r2 as (Key angle) of (Key (Picked unit)) in SF_Hash
                              • Hashtable - Save SF_Reals[13] as (Key speed) of (Key (Picked unit)) in SF_Hash
                              • Special Effect - Create a special effect attached to the chest of u4 using SF_Effects[0]
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • (SF KB <gen> is on) Equal to False
                                • Then - Actions
                                  • Trigger - Turn on SF KB <gen>
                                • Else - Actions
                            • Else - Actions
                              • Special Effect - Create a special effect attached to the sprite first of u4 using SF_Effects[0]
                          • Special Effect - Destroy (Last created special effect)
                        • Else - Actions
                  • -------- -------------------------------------------------- --------
                  • Set r1 = ((Load (Key distance) of ID from SF_Hash) + SF_Reals[4])
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • r1 Less than SF_Reals[1]
                    • Then - Actions
                      • Hashtable - Save r1 as (Key distance) of ID in SF_Hash
                    • Else - Actions
                      • Custom script: call DestroyGroup(udg_g1)
                      • Hashtable - Save 2 as (Key phase) of ID in SF_Hash
                  • Custom script: call RemoveLocation(udg_p2)
                  • Custom script: call RemoveLocation(udg_p3)
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (u2 is alive) Equal to True
                • Then - Actions
                  • Set player = (Owner of u2)
                  • Set r1 = (Load (Key damageAoE) of ID from SF_Hash)
                  • -------- -------------------------------------------------- --------
                  • Set p1 = (Position of u1)
                  • Custom script: set bj_wantDestroyGroup = true
                  • Unit Group - Pick every unit in (Units within SF_Reals[9] of p1 matching ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of player) Equal to True))) and do (Actions)
                    • Loop - Actions
                      • Set u4 = (Picked unit)
                      • Custom script: call UnitDamageTarget( udg_u2 , udg_u4 , udg_r1 , false , true , ATTACK_TYPE_NORMAL , DAMAGE_TYPE_NORMAL , WEAPON_TYPE_WHOKNOWS )
                      • Special Effect - Create a special effect attached to the chest of u4 using SF_Effects[1]
                      • Special Effect - Destroy (Last created special effect)
                  • Custom script: call RemoveLocation(udg_p1)
                  • -------- -------------------------------------------------- --------
                  • Set p1 = (Position of u3)
                  • Custom script: set bj_wantDestroyGroup = true
                  • Unit Group - Pick every unit in (Units within SF_Reals[9] of p1 matching ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of player) Equal to True))) and do (Actions)
                    • Loop - Actions
                      • Set u4 = (Picked unit)
                      • Custom script: call UnitDamageTarget( udg_u2 , udg_u4 , udg_r1 , false , true , ATTACK_TYPE_NORMAL , DAMAGE_TYPE_NORMAL , WEAPON_TYPE_WHOKNOWS )
                      • Special Effect - Create a special effect attached to the chest of u4 using SF_Effects[1]
                      • Special Effect - Destroy (Last created special effect)
                  • Custom script: call RemoveLocation(udg_p1)
                • Else - Actions
              • Unit - Add a 0.01 second Generic expiration timer to u1
              • Unit - Add a 0.01 second Generic expiration timer to u3
              • Lightning - Destroy l1
              • Unit Group - Remove u1 from SF_Balls
              • Hashtable - Clear all child hashtables of child ID in SF_Hash
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (SF_Balls is empty) Equal to True
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
  • SF KB
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in SF_KB and do (Actions)
        • Loop - Actions
          • Set u1 = (Picked unit)
          • Custom script: set udg_ID = GetHandleId(udg_u1)
          • Custom script: set udg_r1 = GetUnitX(udg_u1)
          • Custom script: set udg_r2 = GetUnitY(udg_u1)
          • Custom script: set udg_r3 = LoadReal( udg_SF_Hash , udg_ID , StringHash("speed") )
          • Custom script: set udg_r4 = LoadReal( udg_SF_Hash , udg_ID , StringHash("angle") )
          • -------- ------------------------------------------------------------ --------
          • Set r3 = (r3 / SF_Reals[14])
          • -------- ------------------------------------------------------------ --------
          • Custom script: set udg_r5 = udg_r1 + udg_r3 * Cos(udg_r4)
          • Custom script: set udg_r6 = udg_r2 + udg_r3 * Sin(udg_r4)
          • -------- ------------------------------------------------------------ --------
          • Item - Show SF_Item
          • -------- ------------------------------------------------------------ --------
          • Custom script: call SetItemPosition( udg_SF_Item , udg_r5 , udg_r6 )
          • -------- ------------------------------------------------------------ --------
          • Custom script: set udg_r1 = GetItemX(udg_SF_Item)
          • Custom script: set udg_r2 = GetItemY(udg_SF_Item)
          • -------- ------------------------------------------------------------ --------
          • Item - Hide SF_Item
          • -------- ------------------------------------------------------------ --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • r1 Equal to r5
              • r2 Equal to r6
              • r3 Greater than or equal to SF_Reals[12]
            • Then - Actions
              • Custom script: call SetUnitX(udg_u1 , udg_r5 )
              • Custom script: call SetUnitY(udg_u1 , udg_r6 )
              • Custom script: call SaveReal ( udg_SF_Hash , udg_ID , StringHash("speed") , udg_r3 )
            • Else - Actions
              • Unit Group - Remove u1 from SF_KB
              • Custom script: call DestroyEffect( LoadEffectHandle( udg_SF_Hash , udg_ID , StringHash("e") ) )
              • Custom script: call FlushChildHashtable(udg_SF_Hash , udg_ID )
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (SF_KB is empty) Equal to True
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
JASS:
scope StaticFence initializer InitTrig_StaticFence

    globals
    
        // The ability's raw code
        private constant integer ABILID = 'A000'
        // The dummy's raw code
        private constant integer DUMMYID = 'h000'
        // The item's raw code
        private constant integer ITEMID = 'I000'
        
        // The lightning's width is this * 2
        private constant real FENCEWIDTH = 150.
        // How far the lighning goes
        private constant real DISTMAX = 700.
        // Average flying height of the balls
        private constant real AVGHEIGHT = 50.
        // How fast the lightning moves
        private constant real SPEED = 15.
        // Base damage
        private constant real DMG = 50.
        // Bonus damage per ability level
        private constant real DMGBONUS = 25.
        // How fast the lightning widens at the beginning
        private constant real WIDTHSPEED = 5.
        // Width of the collision rectangle / 2
        private constant real WIDTH = 16.
        // AoE of Explosion
        private constant real AOE = 150.
        // Base damage of explosion
        private constant real DMGAOE = 50.
        // Bonus damage per ability level of the explosion
        private constant real DMGBONUSAOE = 25.
        // Minimum speed of knockback, less than this -> unit stops
        private constant real KBNMINSPEED = 3.
        // Initial speed of knockback
        private constant real KBSPEED = 30.
        // How quickly the knockback speed slows down
        private constant real KBDECELERATION = 1.1
        // How quickly the balls change flying height
        private constant real FHCHANGE = 0.05
        // Extra width of the collision rectangle due to the balls
        private constant real RECTOFFSET = 32
        // Initial visibility of the ball and lightning
        private constant integer VISIBILITY = 0
        
        // Period of timers
        private constant real TIMEOUT = 0.03
        
        // The lightning's type
        private constant string LIGHTNINGTYPE = "DRAM"
        
        private constant attacktype ATKTYPE = ATTACK_TYPE_NORMAL
        private constant damagetype DMGTYPE = DAMAGE_TYPE_LIGHTNING
        
        // Effect when the fence hits a unit
        private constant string HITEFFECT = "Abilities\\Weapons\\FaerieDragonMissile\\FaerieDragonMissile.mdl"
        // Effect on units when hit by the final explosion
        private constant string AOEEFFECT = "Abilities\\Spells\\Orc\\Purge\\PurgeBuffTarget.mdl"
        // Effect on units when knocked back
        private constant string KBEFFECT = "Abilities\\Spells\\Other\\Tornado\\Tornado_Target.mdl"
        
        /*~~~~~~~~~~~ Dont edit these ~~~~~~~~~~~~*/
        private integer kbs = 0
        private integer balls = 0
        private item PATH_ITEM
        private player plr
        private unit un
        private group grp = CreateGroup()
        
        private real re1
        private real re2
        private real re3
        private real re4
        private real re5
        private real re6
        private real re7
        private real re8
        
        private hashtable hash = InitHashtable()
        private group ballGroup = CreateGroup()
        private timer ballTimer = CreateTimer()
        private group kbGroup = CreateGroup()
        private timer kbTimer = CreateTimer()
        /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    
    endglobals
    
    
    // Returns a boolean that tells whether the point is inside a rectangle.
    // (px , py) = Point to check
    // (cx , cy) = lower left corner of the rect
    // (ax , ay) = upper left corner
    // (bx , by) = lower right corner
    function IsPointInRect takes real px , real py , real cx , real cy , real ax , real ay , real bx , real by returns boolean        
        local real dot1 = (px-cx)*(ax-cx) + (py-cy)*(ay-cy)
        local real dot2 = (ax-cx)*(ax-cx) + (ay-cy)*(ay-cy)
        local real dot3 = (px-cx)*(bx-cx) + (py-cy)*(by-cy)
        local real dot4 = (bx-cx)*(bx-cx) + (by-cy)*(by-cy)
        
        return dot1 >= 0 and dot1 <= dot2 and dot3 >= 0 and dot3 <= dot4
    endfunction
    
    
    private function SF_kb takes nothing returns nothing
        local unit u = GetEnumUnit()
        local integer id = GetHandleId(u)
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local real x2
        local real y2
        local real speed = LoadReal( hash , id , StringHash("speed") )
        local real angle = LoadReal( hash , id , StringHash("angle") )
        
        set speed = speed / KBDECELERATION
        set x = x + speed * Cos(angle)
        set y = y + speed * Sin(angle)
            
        call SetItemVisible( PATH_ITEM , true )
        call SetItemPosition( PATH_ITEM , x , y )
        set x2 = GetItemX(PATH_ITEM)
        set y2 = GetItemY(PATH_ITEM)
        call SetItemVisible( PATH_ITEM , false )
            
        if x == x2 and y == y2 and speed > 2. then
            call SetUnitX( u , x )
            call SetUnitY( u , y )
            call SaveReal ( hash , id , StringHash("speed") , speed )
        else
            call DestroyEffect(LoadEffectHandle( hash , id , StringHash("e") ) )
            call GroupRemoveUnit( kbGroup , u )
            call FlushChildHashtable( hash , id )
            
            set kbs = kbs - 1
            if kbs == 0 then
                call PauseTimer(kbTimer)
            endif
        endif
        set u = null
    endfunction
    
    
    private function kbTimerExpire takes nothing returns nothing
        call ForGroup( kbGroup , function SF_kb )
    endfunction
    
    
    private function UnitFilterExplode takes nothing returns boolean
        local unit u = GetFilterUnit()
        if  GetWidgetLife(u) > 0.405 and /*
        */  IsUnitEnemy( u , plr )       /*
     */ then
            call UnitDamageTarget( un , u , re1 , false , true , ATKTYPE , DMGTYPE , WEAPON_TYPE_WHOKNOWS )
            if IsUnitType( u , UNIT_TYPE_STRUCTURE ) then
                call DestroyEffect( AddSpecialEffectTarget( AOEEFFECT , u , "sprite first" ) )
            else
                call DestroyEffect( AddSpecialEffectTarget( AOEEFFECT , u , "chest" ) )
            endif
        endif
        set u = null
        return false
    endfunction
    
    
    private function UnitFilter takes nothing returns boolean
        local unit u = GetFilterUnit()
        local integer id
        if  GetWidgetLife(u) > 0.405 and /*
        */  not(IsUnitInGroup( u , bj_lastCreatedGroup )) and /*
        */  IsUnitEnemy( u , plr ) and /*
        */  IsUnitType( u , UNIT_TYPE_GROUND ) and /*
        */  IsPointInRect( GetUnitX(u) , GetUnitY(u) , re1 , re2 , re3 , re4 , re5 , re6 ) /*
     */ then
            call GroupAddUnit( bj_lastCreatedGroup , u )
            call UnitDamageTarget( un , u , re7 , false , true , ATKTYPE , DMGTYPE , WEAPON_TYPE_WHOKNOWS )
            if IsUnitType( u , UNIT_TYPE_STRUCTURE ) then
                call DestroyEffect( AddSpecialEffectTarget( HITEFFECT , u , "sprite first" ) )
            else
                set id = GetHandleId(u)
                call GroupAddUnit( kbGroup , u )
                call DestroyEffect( AddSpecialEffectTarget( HITEFFECT , u , "chest" ) )
                call SaveEffectHandle( hash , id , StringHash("e") , AddSpecialEffectTarget( KBEFFECT , u , "origin" ) )
                call SaveReal( hash , id , StringHash("speed") , KBSPEED )
                call SaveReal( hash , id , StringHash("angle") , re8 )
                
                set kbs = kbs + 1
                if kbs == 1 then
                    call TimerStart( kbTimer , TIMEOUT , true , function kbTimerExpire )
                endif
            endif
        else
        endif
        set u = null
        return false
    endfunction
    
    
        private function ballLoop takes nothing returns nothing
        local unit u = GetEnumUnit()
        local integer ID = GetHandleId(u)
        local unit caster = LoadUnitHandle( hash , ID , StringHash("caster") )
        local unit other = LoadUnitHandle( hash , ID , StringHash("other") )
        local integer phase = LoadInteger( hash , ID , StringHash("phase") )
        local lightning l = LoadLightningHandle( hash , ID , StringHash("l") )
        local real real1
        local real real2
        local real real3
        local real real4
        local real real5
        local integer i
        local location loc1
        local location loc2
        
        
        if phase != 2 and GetWidgetLife(caster) > 0.405 then
            if phase == 0 then
                set real1 = LoadReal( hash , ID , StringHash("angleSide") )
                set real2 = real1 - bj_PI
                set real3 = LoadReal( hash , ID , StringHash("sideOffset") ) + WIDTHSPEED
                set real4 = LoadReal( hash , ID , StringHash("x") )
                set real5 = LoadReal( hash , ID , StringHash("y") )
                if real3 >= FENCEWIDTH then
                    set real3 = FENCEWIDTH
                    call SetUnitX( u , real4 + real3 * Cos(real1) )
                    call SetUnitY( u , real5 + real3 * Sin(real1) )
                    call SetUnitX( other , real4 + real3 * Cos(real2) )
                    call SetUnitY( other , real5 + real3 * Sin(real2) )
                    call SetUnitVertexColor( u , 255 , 255 , 255 , 255 )
                    call SetUnitVertexColor( other , 255 , 255 , 255 , 255 )
                    call SetLightningColor( l , 1. , 1. , 1. , 1. )
                    call SaveInteger( hash , ID , StringHash("phase") , 1 )
                else
                    call SetUnitX( u , real4 + real3 * Cos(real1) )
                    call SetUnitY( u , real5 + real3 * Sin(real1) )
                    call SetUnitX( other , real4 + real3 * Cos(real2) )
                    call SetUnitY( other , real5 + real3 * Sin(real2) )
                    set i = LoadInteger( hash , ID , StringHash("alpha") ) + LoadInteger( hash , ID , StringHash("visiSpeed") )
                    call SetUnitVertexColor( u , 255 , 255 , 255 , i )
                    call SetUnitVertexColor( other , 255 , 255 , 255 , i )
                    call SetLightningColor( l , 1. , 1. , 1. , I2R(i) / 255 )
                    call SaveInteger( hash , ID , StringHash("alpha") , i )
                    call SaveReal( hash , ID , StringHash("sideOffset") , real3 )
                endif
                set loc1 = GetUnitLoc(u)
                set loc2 = GetUnitLoc(other)
                call MoveLightningEx( l , true , GetUnitX(u) , GetUnitY(u) , GetLocationZ(loc1) + GetUnitFlyHeight(u) , GetUnitX(other) , GetUnitY(other) , GetLocationZ(loc2) + GetUnitFlyHeight(other) )
                call RemoveLocation(loc1)
                call RemoveLocation(loc2)
            else
                // Changes the the flying height of the balls
                set real1 = LoadReal( hash , ID , StringHash("phase1") )
                set real2 = LoadReal( hash , ID , StringHash("phase2") )
                call SetUnitFlyHeight( u , AVGHEIGHT + AVGHEIGHT / 2 * Sin(real1) , 0. )
                call SetUnitFlyHeight( other , AVGHEIGHT + AVGHEIGHT / 2 * Sin(real2) , 0. )
                call SaveReal( hash , ID , StringHash("phase1") , real1 + FHCHANGE )
                call SaveReal( hash , ID , StringHash("phase2") , real2 + FHCHANGE )
                
                set re8 = LoadReal( hash , ID , StringHash("angle") )
                set real2 = GetUnitX(u) + SPEED * Cos(re8)
                set real3 = GetUnitY(u) + SPEED * Sin(re8)

                set real1 = re8 - bj_PI / 2
                set real4 = real2 + 2 * FENCEWIDTH * Cos(real1)
                set real5 = real3 + 2 * FENCEWIDTH * Sin(real1)
                
                call SetUnitX( u , real2 )
                call SetUnitY( u , real3 )
                call SetUnitX( other , real4 )
                call SetUnitY( other , real5 )
                
                set loc1 = Location( real2 , real3 )
                set loc2 = Location( real4 , real5 )
                call MoveLightningEx( l , true , real2 , real3 , GetLocationZ(loc1) + GetUnitFlyHeight(u) , real4 , real5 , GetLocationZ(loc2) + GetUnitFlyHeight(other) )
                call RemoveLocation(loc1)
                call RemoveLocation(loc2)
                
                // Lower left corner
                set real1 = re8 + 3*bj_PI/4
                set real5 = SquareRoot(RECTOFFSET*RECTOFFSET*2)
                set re1 = real2 + real5 * Cos(real1)
                set re2 = real3 + real5 * Sin(real1)
                // Upper left corner
                set real1 = re8 + bj_PI/4
                set re3 = real2 + real5 * Cos(real1)
                set re4 = real3 + real5 * Sin(real1)
                // Lower right corner
                set real1 = re8 - bj_PI/2
                set re5 = re1 + 2 * ( FENCEWIDTH + RECTOFFSET ) * Cos(real1)
                set re6 = re2 + 2 * ( FENCEWIDTH + RECTOFFSET ) * Sin(real1)
                
                set bj_lastCreatedGroup = LoadGroupHandle( hash , ID , StringHash("group") )
                set plr = GetOwningPlayer(caster)
                set un = caster
                set re7 = LoadReal( hash , ID , StringHash("damage") )
                call GroupEnumUnitsInRange( grp , re1 , re2 , 2.5 * FENCEWIDTH , function UnitFilter ) 
                call GroupClear(grp)
                
                set real1 = LoadReal( hash , ID , StringHash("distance") )
                if real1 < DISTMAX then
                    call SaveReal( hash , ID , StringHash("distance") , real1 + SPEED )
                else
                    call DestroyGroup(bj_lastCreatedGroup)
                    call SaveInteger( hash , ID , StringHash("phase") , 2 )
                endif
            endif
        else
            if GetWidgetLife(caster) > 0.405 then
                set un = caster
                set plr = GetOwningPlayer(caster)
                set re1 = LoadReal( hash , ID , StringHash("damageAOE") )

                call GroupEnumUnitsInRange( grp , GetUnitX(u) , GetUnitY(u) , AOE , function UnitFilterExplode ) 
                call GroupClear(grp)
                
                call GroupEnumUnitsInRange( grp , GetUnitX(other) , GetUnitY(other) , AOE , function UnitFilterExplode ) 
                call GroupClear(grp)
            endif
            call UnitApplyTimedLife( u , 1 , 0.01 )
            call UnitApplyTimedLife( other , 1 , 0.01 )
            call DestroyLightning(l)
            call GroupRemoveUnit( ballGroup , u )
            call FlushChildHashtable( hash , ID )
            
            set balls = balls - 1
            if balls == 0 then
                call PauseTimer(ballTimer)
            endif
        endif
        
        set l = null
        set loc1 = null
        set loc2 = null
        set u = null
        set other = null
        set caster = null
    endfunction
    
    
    private function ballTimerExpire takes nothing returns nothing
        call ForGroup( ballGroup , function ballLoop )
    endfunction
    

    private function SF_Actions takes nothing returns nothing
        local unit u = GetTriggerUnit()
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local real facing = GetUnitFacing(u)
        local location loc = GetUnitLoc(u)
        local integer level = GetUnitAbilityLevel( u , ABILID ) - 1
        local integer ID
        
        local real rnd = GetRandomReal( 0 , 2 * bj_PI )
        set bj_lastCreatedUnit = CreateUnit( Player(15) , DUMMYID , x , y , facing )
        set ID = GetHandleId(bj_lastCreatedUnit)
        call GroupAddUnit( ballGroup , bj_lastCreatedUnit )
        call SetUnitExploded( bj_lastCreatedUnit , true )
        call SetUnitFlyHeight( bj_lastCreatedUnit , AVGHEIGHT , 0. )
        call SetUnitFlyHeight( bj_lastCreatedUnit , AVGHEIGHT + AVGHEIGHT / 2 * Sin(rnd) , 0. )
        call SetUnitVertexColor( bj_lastCreatedUnit , 255 , 255 , 255 , VISIBILITY )
        call SaveReal( hash , ID , StringHash("phase1") , rnd )
        
        set rnd = GetRandomReal( 0 , 2 * bj_PI )
        set bj_lastCreatedUnit = CreateUnit( Player(15) , DUMMYID , x , y , facing )
        call SetUnitExploded( bj_lastCreatedUnit , true )
        call SetUnitFlyHeight( bj_lastCreatedUnit , AVGHEIGHT , 0. )
        call SetUnitFlyHeight( bj_lastCreatedUnit , AVGHEIGHT + AVGHEIGHT / 2 * Sin(rnd) , 0. )
        call SetUnitVertexColor( bj_lastCreatedUnit , 255 , 255 , 255 , VISIBILITY )
        call SaveReal( hash , ID , StringHash("phase2") , rnd )
        
        set bj_lastCreatedLightning = AddLightningEx( LIGHTNINGTYPE , true , x , y , GetLocationZ(loc) + AVGHEIGHT , x + 1 , y + 1 , GetLocationZ(loc) + AVGHEIGHT )
        call SetLightningColor( bj_lastCreatedLightning , 1 , 1 , 1 , VISIBILITY )
        
        call SaveReal( hash , ID , StringHash("x") , x )
        call SaveReal( hash , ID , StringHash("y") , y )
        call SaveReal( hash , ID , StringHash("angle") , facing * bj_DEGTORAD )
        call SaveReal( hash , ID , StringHash("sideOffset") , 0. )
        call SaveReal( hash , ID , StringHash("angleSide") , (facing + 90) * bj_DEGTORAD )
        call SaveReal( hash , ID , StringHash("damage") , DMG + DMGBONUS * level )
        call SaveReal( hash , ID , StringHash("damageAOE") , DMGAOE + DMGBONUSAOE * level )
        call SaveUnitHandle( hash , ID , StringHash("caster") , u )
        call SaveUnitHandle( hash , ID , StringHash("other") , bj_lastCreatedUnit )
        call SaveInteger( hash , ID , StringHash("alpha") , VISIBILITY )
        call SaveInteger( hash , ID , StringHash("visiSpeed") , R2I(I2R(255-VISIBILITY) / ( FENCEWIDTH / WIDTHSPEED )) )
        call SaveLightningHandle( hash , ID , StringHash("l") , bj_lastCreatedLightning  )
        call SaveGroupHandle( hash , ID , StringHash("group") , CreateGroup() )
        
        set balls = balls + 1
        if balls == 1 then
            call TimerStart( ballTimer , TIMEOUT , true , function ballTimerExpire )
        endif
        
        call RemoveLocation(loc)
        set u = null
    endfunction
    
    private function SF_Conditions takes nothing returns boolean
        return GetSpellAbilityId() == ABILID
    endfunction
    

    private function InitTrig_StaticFence takes nothing returns nothing
        local trigger t = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( t , EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( t , Condition( function SF_Conditions ) )
        call TriggerAddAction( t , function SF_Actions )
        set PATH_ITEM = CreateItem( ITEMID , 0 , 0 )
        call SetItemVisible( PATH_ITEM , false )
    endfunction

endscope

the notice from Maker : IsPointInRect update:

JASS:
library PointInRect

    // Returns a boolean that tells whether the point is inside a rectangle.
    // (px , py) = Point to check
    // (cx , cy) = lower left corner of the rect
    // (ax , ay) = upper left corner
    // (bx , by) = lower right corner
    function IsPointInRect takes real px , real py , real cx , real cy , real ax , real ay , real bx , real by returns boolean        
        local real dot1 = (px-cx)*(ax-cx) + (py-cy)*(ay-cy)
        local real dot2 = (ax-cx)*(ax-cx) + (ay-cy)*(ay-cy)
        local real dot3 = (px-cx)*(bx-cx) + (py-cy)*(by-cy)
        local real dot4 = (bx-cx)*(bx-cx) + (by-cy)*(by-cy)
        
        return dot1 >= 0 and dot1 <= dot2 and dot3 >= 0 and dot3 <= dot4
    endfunction
    
endlibrary






Keywords:
static, fence, dragging, cool, electric
Contents

Static Fence (Map)

Reviews
12th Dec 2015 IcemanBo: Too long as NeedsFix. Rejected. 11th Jul 2011 Bribe: You create two dummy units with nearly identical code, but the code could be cut in half if you centralize it better. You can shorten it like this: SF Cast...

Moderator

M

Moderator

12th Dec 2015
IcemanBo: Too long as NeedsFix. Rejected.


11th Jul 2011
Bribe:

You create two dummy units with nearly identical code, but the code could be cut in half if you centralize it better. You can shorten it like this:

  • SF Cast
    • Actions
      • For each (Integer A) from 1 to 2 do:
        • Loop - Actions
          • Set r3 = (Random real number between 0 and 360.00)
          • Unit - Create 1 SF_Dummy_Type for Neutral Passive at p1 facing r1 degrees
          • Set u2 = (Last created unit)
          • Unit - Make u2 Explode on death
          • Animation - Change u2 flying height to SF_Reals[2] at 0.00
          • Animation - Change u2 flying height to (SF_Reals[2] + ((SF_Reals[2] / 2.00) x (Sin(r3)))) at 600.00
          • Animation - Change u2's vertex coloring to (100% 100% 100%) with r2% transparency
          • Custom script: call UnitAddAbility(udg_u2 , 'Arav')
      • Custom script: set udg_ID = GetHandleId(udg_u2)
      • Unit Group - Add u2 to SF_Balls
      • Hashtable - Save r3 as (Key phase2) of ID in SF_Hash
Duplicate text is almost always avoidable.

The SF_Reals array should be split into multiple variables:
Why?
1. Preserves readability
2. Is a lighter load on the computer (less work)
3. Easier to maintain/moderate
 
Level 10
Joined
Apr 25, 2009
Messages
296
  • SF Init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set SF_Hash = (Last created hashtable)
      • -------- -------------------------------------------------- --------
      • -------- The ability --------
      • -------- -------------------------------------------------- --------
      • Set SF_Ability = Static Fence
      • -------- -------------------------------------------------- --------
      • -------- Dummy unit type --------
      • -------- -------------------------------------------------- --------
      • Set SF_Dummy_Type = SF Dummy
      • -------- -------------------------------------------------- --------
      • -------- Dummy item for collision checking --------
      • -------- -------------------------------------------------- --------
      • Set SF_Item_Type = Collision Item
      • Custom script: set udg_SF_Item = CreateItem( udg_SF_Item_Type , 0 , 0 )
      • Item - Hide SF_Item
      • -------- -------------------------------------------------- --------
      • -------- Lightning's type --------
      • -------- -------------------------------------------------- --------
      • Set SF_Lightning = DRAM
      • -------- -------------------------------------------------- --------
      • -------- Effect when damage is taken from the fence --------
      • Set SF_Effects[0] = Abilities\Weapons\FaerieDragonMissile\FaerieDragonMissile.mdl
      • -------- Effect when damage is taken from AoE explosion --------
      • Set SF_Effects[1] = Abilities\Spells\Orc\Purge\PurgeBuffTarget.mdl
      • -------- Knockback effect attached to origin --------
      • Set SF_Effects[2] = Abilities\Spells\Other\Tornado\Tornado_Target.mdl
      • -------- -------------------------------------------------- --------
      • -------- Ball offset, how far away to left and right of the caster will the balls go --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[0] = 150.00
      • -------- -------------------------------------------------- --------
      • -------- Ball max distance, how far the balls travel --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[1] = 700.00
      • -------- -------------------------------------------------- --------
      • -------- Ball average flying height --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[2] = 50.00
      • -------- -------------------------------------------------- --------
      • -------- Initial visibility of the balls and lightning --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[3] = 0.00
      • -------- -------------------------------------------------- --------
      • -------- Ball speed --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[4] = 15.00
      • -------- -------------------------------------------------- --------
      • -------- Damage, base --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[5] = 50.00
      • -------- -------------------------------------------------- --------
      • -------- Damage, bonus per ability level --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[6] = 25.00
      • -------- -------------------------------------------------- --------
      • -------- Ball speed sideways --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[7] = 5.00
      • -------- -------------------------------------------------- --------
      • -------- Lightning width / 2 --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[8] = 16.00
      • -------- -------------------------------------------------- --------
      • -------- Explosion AoE --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[9] = 150.00
      • -------- -------------------------------------------------- --------
      • -------- AoE Damage, base --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[10] = 50.00
      • -------- -------------------------------------------------- --------
      • -------- AoE damage, bonus per ability level --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[11] = 25.00
      • -------- -------------------------------------------------- --------
      • -------- Knocback minimum speed --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[12] = 3.00
      • -------- -------------------------------------------------- --------
      • -------- Knocback initial speed --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[13] = 30.00
      • -------- -------------------------------------------------- --------
      • -------- Knocback deceleration --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[14] = 1.10
      • -------- -------------------------------------------------- --------
      • -------- Flying height change speed --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[15] = 8.00
      • -------- -------------------------------------------------- --------
      • -------- Rectangle extra offset --------
      • -------- -------------------------------------------------- --------
      • Set SF_Reals[16] = 32.00
  • SF Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to SF_Ability
    • Actions
      • Set u1 = (Triggering unit)
      • Set p1 = (Position of u1)
      • Set r1 = (Facing of u1)
      • Set i1 = ((Level of SF_Ability for u1) - 1)
      • Set r2 = (100.00 - (SF_Reals[3] x 100.00))
      • -------- -------------------------------------------------- --------
      • Set r3 = (Random real number between 0.00 and 360.00)
      • Unit - Create 1 SF_Dummy_Type for Neutral Passive at p1 facing r1 degrees
      • Set u2 = (Last created unit)
      • Custom script: set udg_ID = GetHandleId(udg_u2)
      • Unit Group - Add u2 to SF_Balls
      • Unit - Make u2 Explode on death
      • Animation - Change u2 flying height to SF_Reals[2] at 0.00
      • Animation - Change u2 flying height to (SF_Reals[2] + ((SF_Reals[2] / 2.00) x (Sin(r3)))) at 600.00
      • Animation - Change u2's vertex coloring to (100.00%, 100.00%, 100.00%) with r2% transparency
      • Custom script: call UnitAddAbility(udg_u2 , 'Arav' )
      • Hashtable - Save r3 as (Key phase1) of ID in SF_Hash
      • -------- -------------------------------------------------- --------
      • Set r3 = (Random real number between 0.00 and 360.00)
      • Unit - Create 1 SF_Dummy_Type for Neutral Passive at p1 facing r1 degrees
      • Set u2 = (Last created unit)
      • Unit - Make u2 Explode on death
      • Animation - Change u2 flying height to SF_Reals[2] at 0.00
      • Animation - Change u2 flying height to (SF_Reals[2] + ((SF_Reals[2] / 2.00) x (Sin(r3)))) at 600.00
      • Animation - Change u2's vertex coloring to (100.00%, 100.00%, 100.00%) with r2% transparency
      • Custom script: call UnitAddAbility(udg_u2 , 'Arav' )
      • Hashtable - Save r3 as (Key phase2) of ID in SF_Hash
      • -------- -------------------------------------------------- --------
      • Custom script: set bj_lastCreatedLightning = AddLightningEx( udg_SF_Lightning , true , GetLocationX(udg_p1) , GetLocationY(udg_p1) , GetLocationZ(udg_p1) + udg_SF_Reals[2] , GetLocationX(udg_p1) , GetLocationY(udg_p1) , GetLocationZ(udg_p1) + udg_SF_Reals[2])
      • Lightning - Change color of (Last created lightning effect) to (1.00 1.00 1.00) with SF_Reals[3] alpha
      • -------- -------------------------------------------------- --------
      • Custom script: set udg_g1 = CreateGroup()
      • -------- -------------------------------------------------- --------
      • Hashtable - Save Handle Ofg1 as (Key group) of ID in SF_Hash
      • Hashtable - Save Handle Ofp1 as (Key center) of ID in SF_Hash
      • Hashtable - Save Handle Ofu1 as (Key caster) of ID in SF_Hash
      • Hashtable - Save Handle Of(Last created unit) as (Key other) of ID in SF_Hash
      • Hashtable - Save Handle Of(Last created lightning effect) as (Key lightning) of ID in SF_Hash
      • Hashtable - Save r1 as (Key angle) of ID in SF_Hash
      • Hashtable - Save r2 as (Key transparency) of ID in SF_Hash
      • Hashtable - Save (r2 / (90.00 / SF_Reals[4])) as (Key visibilitySpeed) of ID in SF_Hash
      • Hashtable - Save 0.00 as (Key sideOffset) of ID in SF_Hash
      • Hashtable - Save (r1 + 90.00) as (Key angleSide) of ID in SF_Hash
      • Hashtable - Save (SF_Reals[5] + (SF_Reals[6] x (Real(i1)))) as (Key damage) of ID in SF_Hash
      • Hashtable - Save (SF_Reals[10] + (SF_Reals[11] x (Real(i1)))) as (Key damageAoE) of ID in SF_Hash
      • -------- -------------------------------------------------- --------
      • Trigger - Turn on SF Loop <gen>
      • -------- -------------------------------------------------- --------
  • SF Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in SF_Balls and do (Actions)
        • Loop - Actions
          • Set u1 = (Picked unit)
          • Set ID = (Key (Picked unit))
          • Set u2 = (Load (Key caster) of ID in SF_Hash)
          • Set u3 = (Load (Key other) of ID in SF_Hash)
          • Set l1 = (Load (Key lightning) of ID in SF_Hash)
          • Set i1 = (Load (Key phase) of ID from SF_Hash)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • i1 Not equal to 2
              • (u2 is alive) Equal to True
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • i1 Equal to 0
                • Then - Actions
                  • Set r1 = (Load (Key angleSide) of ID from SF_Hash)
                  • Set r2 = (r1 - 180.00)
                  • Set r3 = ((Load (Key sideOffset) of ID from SF_Hash) + SF_Reals[7])
                  • Set p1 = (Load (Key center) of ID in SF_Hash)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • r3 Greater than or equal to SF_Reals[0]
                    • Then - Actions
                      • Set r3 = SF_Reals[0]
                      • Set p2 = (p1 offset by r3 towards r1 degrees)
                      • Set p3 = (p1 offset by r3 towards r2 degrees)
                      • Unit - Move u1 instantly to p2
                      • Unit - Move u3 instantly to p3
                      • Animation - Change u1's vertex coloring to (100.00%, 100.00%, 100.00%) with 0.00% transparency
                      • Animation - Change u3's vertex coloring to (100.00%, 100.00%, 100.00%) with 0.00% transparency
                      • Lightning - Change color of l1 to (1.00 1.00 1.00) with 1.00 alpha
                      • Custom script: call RemoveLocation(udg_p1)
                      • Hashtable - Save 1 as (Key phase) of ID in SF_Hash
                    • Else - Actions
                      • Set p2 = (p1 offset by r3 towards r1 degrees)
                      • Set p3 = (p1 offset by r3 towards r2 degrees)
                      • Unit - Move u1 instantly to p2
                      • Unit - Move u3 instantly to p3
                      • Set r4 = ((Load (Key transparency) of ID from SF_Hash) - (Load (Key visibilitySpeed) of ID from SF_Hash))
                      • Animation - Change u1's vertex coloring to (100.00%, 100.00%, 100.00%) with r4% transparency
                      • Animation - Change u3's vertex coloring to (100.00%, 100.00%, 100.00%) with r4% transparency
                      • Lightning - Change color of l1 to (1.00 1.00 1.00) with (1.00 - (r4 / 100.00)) alpha
                      • Hashtable - Save r3 as (Key sideOffset) of ID in SF_Hash
                      • Hashtable - Save r4 as (Key transparency) of ID in SF_Hash
                  • Custom script: call MoveLightningEx( udg_l1 , true , GetLocationX(udg_p2) , GetLocationY(udg_p2) , GetLocationZ(udg_p2) + GetUnitFlyHeight(udg_u1) , GetLocationX(udg_p3) , GetLocationY(udg_p3) , GetLocationZ(udg_p3) + GetUnitFlyHeight(udg_u3) )
                  • Custom script: call RemoveLocation(udg_p2)
                  • Custom script: call RemoveLocation(udg_p3)
                • Else - Actions
                  • Set r1 = (Load (Key damage) of ID from SF_Hash)
                  • Set r2 = (Load (Key angle) of ID from SF_Hash)
                  • Set p1 = (Position of u1)
                  • Set p2 = (p1 offset by SF_Reals[4] towards r2 degrees)
                  • Set p3 = (p2 offset by (2.00 x SF_Reals[0]) towards (r2 - 90.00) degrees)
                  • -------- -------------------------------------------------- --------
                  • Unit - Move u1 instantly to p2
                  • Unit - Move u3 instantly to p3
                  • -------- -------------------------------------------------- --------
                  • Set r3 = (Load (Key phase1) of ID from SF_Hash)
                  • Animation - Change u1 flying height to (SF_Reals[2] + ((SF_Reals[2] / 2.00) x (Sin(r3)))) at 0.00
                  • Hashtable - Save (r3 + SF_Reals[15]) as (Key phase1) of ID in SF_Hash
                  • Set r3 = (Load (Key phase2) of ID from SF_Hash)
                  • Animation - Change u3 flying height to (SF_Reals[2] + ((SF_Reals[2] / 2.00) x (Sin(r3)))) at 0.00
                  • Hashtable - Save (r3 + SF_Reals[15]) as (Key phase2) of ID in SF_Hash
                  • -------- -------------------------------------------------- --------
                  • Custom script: call MoveLightningEx( udg_l1 , true , GetLocationX(udg_p2) , GetLocationY(udg_p2) , GetLocationZ(udg_p2) + GetUnitFlyHeight(udg_u1) , GetLocationX(udg_p3) , GetLocationY(udg_p3) , GetLocationZ(udg_p3) + GetUnitFlyHeight(udg_u3) )
                  • -------- -------------------------------------------------- --------
                  • Custom script: set udg_r2 = udg_r2 * bj_DEGTORAD
                  • Custom script: set udg_r3 = GetUnitX(udg_u1) + udg_SF_Reals[16] * Cos(udg_r2+bj_PI/2)
                  • Custom script: set udg_r4 = GetUnitY(udg_u1) + udg_SF_Reals[16] * Sin(udg_r2+bj_PI/2)
                  • -------- Lower left corner --------
                  • Custom script: set udg_r5 = udg_r3 + udg_SF_Reals[8] * Cos(udg_r2-bj_PI)
                  • Custom script: set udg_r6 = udg_r4 + udg_SF_Reals[8] * Sin(udg_r2-bj_PI)
                  • -------- Upper left corner --------
                  • Custom script: set udg_r7 = udg_r3 + udg_SF_Reals[8] * Cos(udg_r2)
                  • Custom script: set udg_r8 = udg_r4 + udg_SF_Reals[8] * Sin(udg_r2)
                  • -------- Lower right corner --------
                  • Custom script: set udg_r9 = udg_r5 + 2 * (udg_SF_Reals[0] + udg_SF_Reals[16]) * Cos(udg_r2-bj_PI/2)
                  • Custom script: set udg_r10 = udg_r6 + 2 * (udg_SF_Reals[0] + udg_SF_Reals[16]) * Sin(udg_r2-bj_PI/2)
                  • -------- -------------------------------------------------- --------
                  • Custom script: call RemoveLocation(udg_p1)
                  • -------- -------------------------------------------------- --------
                  • Set player = (Owner of u2)
                  • Set g1 = (Load (Key group) of ID in SF_Hash)
                  • Custom script: set bj_wantDestroyGroup = true
                  • Unit Group - Pick every unit in (Units within (2.50 x SF_Reals[0]) of p2 matching ((((Matching unit) is alive) Equal to True) and ((((Matching unit) belongs to an enemy of player) Equal to True) and (((Matching unit) is A ground unit) Equal to True)))) and do (Actions)
                    • Loop - Actions
                      • Set u4 = (Picked unit)
                      • Custom script: set udg_SF_Boolean = IsPointInRect( GetUnitX(udg_u4) , GetUnitY(udg_u4) , udg_r5 , udg_r6 , udg_r7 , udg_r8 , udg_r9 , udg_r10 )
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • (u4 is in g1) Equal to False
                          • SF_Boolean Equal to True
                        • Then - Actions
                          • Unit Group - Add u4 to g1
                          • Custom script: call UnitDamageTarget( udg_u2 , udg_u4 , udg_r1 , false , true , ATTACK_TYPE_NORMAL , DAMAGE_TYPE_NORMAL , WEAPON_TYPE_WHOKNOWS )
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • (u4 is A structure) Equal to False
                            • Then - Actions
                              • Unit Group - Add u4 to SF_KB
                              • Special Effect - Create a special effect attached to the origin of u4 using SF_Effects[2]
                              • Hashtable - Save Handle Of(Last created special effect) as (Key e) of (Key (Picked unit)) in SF_Hash
                              • Hashtable - Save r2 as (Key angle) of (Key (Picked unit)) in SF_Hash
                              • Hashtable - Save SF_Reals[13] as (Key speed) of (Key (Picked unit)) in SF_Hash
                              • Special Effect - Create a special effect attached to the chest of u4 using SF_Effects[0]
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • (SF KB <gen> is on) Equal to False
                                • Then - Actions
                                  • Trigger - Turn on SF KB <gen>
                                • Else - Actions
                            • Else - Actions
                              • Special Effect - Create a special effect attached to the sprite first of u4 using SF_Effects[0]
                          • Special Effect - Destroy (Last created special effect)
                        • Else - Actions
                  • -------- -------------------------------------------------- --------
                  • Set r1 = ((Load (Key distance) of ID from SF_Hash) + SF_Reals[4])
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • r1 Less than SF_Reals[1]
                    • Then - Actions
                      • Hashtable - Save r1 as (Key distance) of ID in SF_Hash
                    • Else - Actions
                      • Custom script: call DestroyGroup(udg_g1)
                      • Hashtable - Save 2 as (Key phase) of ID in SF_Hash
                  • Custom script: call RemoveLocation(udg_p2)
                  • Custom script: call RemoveLocation(udg_p3)
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (u2 is alive) Equal to True
                • Then - Actions
                  • Set player = (Owner of u2)
                  • Set r1 = (Load (Key damageAoE) of ID from SF_Hash)
                  • -------- -------------------------------------------------- --------
                  • Set p1 = (Position of u1)
                  • Custom script: set bj_wantDestroyGroup = true
                  • Unit Group - Pick every unit in (Units within SF_Reals[9] of p1 matching ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of player) Equal to True))) and do (Actions)
                    • Loop - Actions
                      • Set u4 = (Picked unit)
                      • Custom script: call UnitDamageTarget( udg_u2 , udg_u4 , udg_r1 , false , true , ATTACK_TYPE_NORMAL , DAMAGE_TYPE_NORMAL , WEAPON_TYPE_WHOKNOWS )
                      • Special Effect - Create a special effect attached to the chest of u4 using SF_Effects[1]
                      • Special Effect - Destroy (Last created special effect)
                  • Custom script: call RemoveLocation(udg_p1)
                  • -------- -------------------------------------------------- --------
                  • Set p1 = (Position of u3)
                  • Custom script: set bj_wantDestroyGroup = true
                  • Unit Group - Pick every unit in (Units within SF_Reals[9] of p1 matching ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of player) Equal to True))) and do (Actions)
                    • Loop - Actions
                      • Set u4 = (Picked unit)
                      • Custom script: call UnitDamageTarget( udg_u2 , udg_u4 , udg_r1 , false , true , ATTACK_TYPE_NORMAL , DAMAGE_TYPE_NORMAL , WEAPON_TYPE_WHOKNOWS )
                      • Special Effect - Create a special effect attached to the chest of u4 using SF_Effects[1]
                      • Special Effect - Destroy (Last created special effect)
                  • Custom script: call RemoveLocation(udg_p1)
                • Else - Actions
              • Unit - Add a 0.01 second Generic expiration timer to u1
              • Unit - Add a 0.01 second Generic expiration timer to u3
              • Lightning - Destroy l1
              • Unit Group - Remove u1 from SF_Balls
              • Hashtable - Clear all child hashtables of child ID in SF_Hash
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (SF_Balls is empty) Equal to True
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
  • SF KB
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in SF_KB and do (Actions)
        • Loop - Actions
          • Set u1 = (Picked unit)
          • Custom script: set udg_ID = GetHandleId(udg_u1)
          • Custom script: set udg_r1 = GetUnitX(udg_u1)
          • Custom script: set udg_r2 = GetUnitY(udg_u1)
          • Custom script: set udg_r3 = LoadReal( udg_SF_Hash , udg_ID , StringHash("speed") )
          • Custom script: set udg_r4 = LoadReal( udg_SF_Hash , udg_ID , StringHash("angle") )
          • -------- ------------------------------------------------------------ --------
          • Set r3 = (r3 / SF_Reals[14])
          • -------- ------------------------------------------------------------ --------
          • Custom script: set udg_r5 = udg_r1 + udg_r3 * Cos(udg_r4)
          • Custom script: set udg_r6 = udg_r2 + udg_r3 * Sin(udg_r4)
          • -------- ------------------------------------------------------------ --------
          • Item - Show SF_Item
          • -------- ------------------------------------------------------------ --------
          • Custom script: call SetItemPosition( udg_SF_Item , udg_r5 , udg_r6 )
          • -------- ------------------------------------------------------------ --------
          • Custom script: set udg_r1 = GetItemX(udg_SF_Item)
          • Custom script: set udg_r2 = GetItemY(udg_SF_Item)
          • -------- ------------------------------------------------------------ --------
          • Item - Hide SF_Item
          • -------- ------------------------------------------------------------ --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • r1 Equal to r5
              • r2 Equal to r6
              • r3 Greater than or equal to SF_Reals[12]
            • Then - Actions
              • Custom script: call SetUnitX(udg_u1 , udg_r5 )
              • Custom script: call SetUnitY(udg_u1 , udg_r6 )
              • Custom script: call SaveReal ( udg_SF_Hash , udg_ID , StringHash("speed") , udg_r3 )
            • Else - Actions
              • Unit Group - Remove u1 from SF_KB
              • Custom script: call DestroyEffect( LoadEffectHandle( udg_SF_Hash , udg_ID , StringHash("e") ) )
              • Custom script: call FlushChildHashtable(udg_SF_Hash , udg_ID )
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (SF_KB is empty) Equal to True
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
JASS:
//TESH.scrollpos=0
//TESH.alwaysfold=0
library PointInRect

    // Returns the dot product between given "vectors".
    private function DotProduct takes real l1 , real a1 , real l2 , real a2 returns real
        return l1*l2*Cos(a1-a2)
    endfunction

    // Returns a boolean that tells whether the point is inside a rectangle.
    // (px , py) = Point to check
    // (cx , cy) = lower left corner of the rect
    // (ax , ay) = upper left corner
    // (bx , by) = lower right corner
    function IsPointInRect takes real px , real py , real cx , real cy , real ax , real ay , real bx , real by returns boolean
        // Vector from lower left corner to point
        local real v_angle = Atan2( py - cy , px - cx )
        local real v_length = SquareRoot( (py-cy)*(py-cy) + (px-cx)*(px-cx) )
        // Vector from lower left corner to upper left corner
        local real v1_angle = Atan2( ay - cy , ax - cx )
        local real v1_length = SquareRoot( (ay-cy)*(ay-cy) + (ax-cx)*(ax-cx) )
        // Vector from lower left corner to lower right corner
        local real v2_angle = Atan2( by - cy , bx - cx )
        local real v2_length = SquareRoot( (by-cy)*(by-cy) + (bx-cx)*(bx-cx) )
        
        // 0 is used for some values since the angle difference will be zero anyway
        local real dot1 = DotProduct(v_length,v_angle,v1_length,v1_angle)
        local real dot2 = DotProduct(v1_length,0,v1_length,0)
        local real dot3 = DotProduct(v_length,v_angle,v2_length,v2_angle)
        local real dot4 = DotProduct(v2_length,0,v2_length,0)
        
        return dot1 >= 0 and dot1 <= dot2 and dot3 >= 0 and dot3 <= dot4
    endfunction
    
endlibrary

Considering the fact that this ability is very well made, I don't want it to die from someone who won't post the triggers.
 
Level 4
Joined
Nov 25, 2010
Messages
59
yeah thats true but considering this is my request and i think everybody deserved it, then i upload it. If you guys don't want me to upload it, what the different if Maker upload it because credit goes to him... By the way thanks for post the trigger i'm newbie so sorry for bothering and if you don't mind , what should i do to make it in my description?
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
Thanks for the comments :)

...what should i do to make it in my description?

Quote his post, then copy everything inside the tags, copy the tags also. Then paste it into the original post.

I'll PM you an updated version soon with minor fixes like getting rid of 2 real variables, optimizing the collision code, adding the Storm Crow ability in object editor and so on.

Expect a vJASS version also.
 
Level 4
Joined
Nov 25, 2010
Messages
59
the 2nd version will be uploaded tommorow because it 11.pm in here actually and i'm tired, thanks again to Maker. About the uploading stuff, we both good and no one complaning because my point here is to share what i think everyone deserves it, (in this case Maker spell) and Maker is also agree with it. Credits goes to Maker (i've already said this 3 times) so have a nice day and hope you all like it
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
Updated vJASS:
JASS:
scope StaticFence initializer InitTrig_StaticFence

    globals
    
        // The ability's raw code
        private constant integer ABILID = 'A000'
        // The dummy's raw code
        private constant integer DUMMYID = 'h000'
        // The item's raw code
        private constant integer ITEMID = 'I000'
        
        // The lightning's width is this * 2
        private constant real FENCEWIDTH = 150.
        // How far the lighning goes
        private constant real DISTMAX = 700.
        // Average flying height of the balls
        private constant real AVGHEIGHT = 50.
        // How fast the lightning moves
        private constant real SPEED = 15.
        // Base damage
        private constant real DMG = 50.
        // Bonus damage per ability level
        private constant real DMGBONUS = 25.
        // How fast the lightning widens at the beginning
        private constant real WIDTHSPEED = 5.
        // Width of the collision rectangle / 2
        private constant real WIDTH = 16.
        // AoE of Explosion
        private constant real AOE = 150.
        // Base damage of explosion
        private constant real DMGAOE = 50.
        // Bonus damage per ability level of the explosion
        private constant real DMGBONUSAOE = 25.
        // Minimum speed of knockback, less than this -> unit stops
        private constant real KBNMINSPEED = 3.
        // Initial speed of knockback
        private constant real KBSPEED = 30.
        // How quickly the knockback speed slows down
        private constant real KBDECELERATION = 1.1
        // How quickly the balls change flying height
        private constant real FHCHANGE = 0.05
        // Extra width of the collision rectangle due to the balls
        private constant real RECTOFFSET = 32
        // Initial visibility of the ball and lightning
        private constant integer VISIBILITY = 0
        
        // Period of timers
        private constant real TIMEOUT = 0.03
        
        // The lightning's type
        private constant string LIGHTNINGTYPE = "DRAM"
        
        private constant attacktype ATKTYPE = ATTACK_TYPE_NORMAL
        private constant damagetype DMGTYPE = DAMAGE_TYPE_LIGHTNING
        
        // Effect when the fence hits a unit
        private constant string HITEFFECT = "Abilities\\Weapons\\FaerieDragonMissile\\FaerieDragonMissile.mdl"
        // Effect on units when hit by the final explosion
        private constant string AOEEFFECT = "Abilities\\Spells\\Orc\\Purge\\PurgeBuffTarget.mdl"
        // Effect on units when knocked back
        private constant string KBEFFECT = "Abilities\\Spells\\Other\\Tornado\\Tornado_Target.mdl"
        
        /*~~~~~~~~~~~ Dont edit these ~~~~~~~~~~~~*/
        private integer kbs = 0
        private integer balls = 0
        private item PATH_ITEM
        private player plr
        private unit un
        private group grp = CreateGroup()
        
        private real re1
        private real re2
        private real re3
        private real re4
        private real re5
        private real re6
        private real re7
        private real re8
        
        private hashtable hash = InitHashtable()
        private group ballGroup = CreateGroup()
        private timer ballTimer = CreateTimer()
        private group kbGroup = CreateGroup()
        private timer kbTimer = CreateTimer()
        /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
    
    endglobals
    
    
    // Returns a boolean that tells whether the point is inside a rectangle.
    // (px , py) = Point to check
    // (cx , cy) = lower left corner of the rect
    // (ax , ay) = upper left corner
    // (bx , by) = lower right corner
    function IsPointInRect takes real px , real py , real cx , real cy , real ax , real ay , real bx , real by returns boolean        
        local real dot1 = (px-cx)*(ax-cx) + (py-cy)*(ay-cy)
        local real dot2 = (ax-cx)*(ax-cx) + (ay-cy)*(ay-cy)
        local real dot3 = (px-cx)*(bx-cx) + (py-cy)*(by-cy)
        local real dot4 = (bx-cx)*(bx-cx) + (by-cy)*(by-cy)
        
        return dot1 >= 0 and dot1 <= dot2 and dot3 >= 0 and dot3 <= dot4
    endfunction
    
    
    private function SF_kb takes nothing returns nothing
        local unit u = GetEnumUnit()
        local integer id = GetHandleId(u)
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local real x2
        local real y2
        local real speed = LoadReal( hash , id , StringHash("speed") )
        local real angle = LoadReal( hash , id , StringHash("angle") )
        
        set speed = speed / KBDECELERATION
        set x = x + speed * Cos(angle)
        set y = y + speed * Sin(angle)
            
        call SetItemVisible( PATH_ITEM , true )
        call SetItemPosition( PATH_ITEM , x , y )
        set x2 = GetItemX(PATH_ITEM)
        set y2 = GetItemY(PATH_ITEM)
        call SetItemVisible( PATH_ITEM , false )
            
        if x == x2 and y == y2 and speed > 2. then
            call SetUnitX( u , x )
            call SetUnitY( u , y )
            call SaveReal ( hash , id , StringHash("speed") , speed )
        else
            call DestroyEffect(LoadEffectHandle( hash , id , StringHash("e") ) )
            call GroupRemoveUnit( kbGroup , u )
            call FlushChildHashtable( hash , id )
            
            set kbs = kbs - 1
            if kbs == 0 then
                call PauseTimer(kbTimer)
            endif
        endif
        set u = null
    endfunction
    
    
    private function kbTimerExpire takes nothing returns nothing
        call ForGroup( kbGroup , function SF_kb )
    endfunction
    
    
    private function UnitFilterExplode takes nothing returns boolean
        local unit u = GetFilterUnit()
        if  GetWidgetLife(u) > 0.405 and /*
        */  IsUnitEnemy( u , plr )       /*
     */ then
            call UnitDamageTarget( un , u , re1 , false , true , ATKTYPE , DMGTYPE , WEAPON_TYPE_WHOKNOWS )
            if IsUnitType( u , UNIT_TYPE_STRUCTURE ) then
                call DestroyEffect( AddSpecialEffectTarget( AOEEFFECT , u , "sprite first" ) )
            else
                call DestroyEffect( AddSpecialEffectTarget( AOEEFFECT , u , "chest" ) )
            endif
        endif
        set u = null
        return false
    endfunction
    
    
    private function UnitFilter takes nothing returns boolean
        local unit u = GetFilterUnit()
        local integer id
        if  GetWidgetLife(u) > 0.405 and /*
        */  not(IsUnitInGroup( u , bj_lastCreatedGroup )) and /*
        */  IsUnitEnemy( u , plr ) and /*
        */  IsUnitType( u , UNIT_TYPE_GROUND ) and /*
        */  IsPointInRect( GetUnitX(u) , GetUnitY(u) , re1 , re2 , re3 , re4 , re5 , re6 ) /*
     */ then
            call GroupAddUnit( bj_lastCreatedGroup , u )
            call UnitDamageTarget( un , u , re7 , false , true , ATKTYPE , DMGTYPE , WEAPON_TYPE_WHOKNOWS )
            if IsUnitType( u , UNIT_TYPE_STRUCTURE ) then
                call DestroyEffect( AddSpecialEffectTarget( HITEFFECT , u , "sprite first" ) )
            else
                set id = GetHandleId(u)
                call GroupAddUnit( kbGroup , u )
                call DestroyEffect( AddSpecialEffectTarget( HITEFFECT , u , "chest" ) )
                call SaveEffectHandle( hash , id , StringHash("e") , AddSpecialEffectTarget( KBEFFECT , u , "origin" ) )
                call SaveReal( hash , id , StringHash("speed") , KBSPEED )
                call SaveReal( hash , id , StringHash("angle") , re8 )
                
                set kbs = kbs + 1
                if kbs == 1 then
                    call TimerStart( kbTimer , TIMEOUT , true , function kbTimerExpire )
                endif
            endif
        else
        endif
        set u = null
        return false
    endfunction
    
    
        private function ballLoop takes nothing returns nothing
        local unit u = GetEnumUnit()
        local integer ID = GetHandleId(u)
        local unit caster = LoadUnitHandle( hash , ID , StringHash("caster") )
        local unit other = LoadUnitHandle( hash , ID , StringHash("other") )
        local integer phase = LoadInteger( hash , ID , StringHash("phase") )
        local lightning l = LoadLightningHandle( hash , ID , StringHash("l") )
        local real real1
        local real real2
        local real real3
        local real real4
        local real real5
        local integer i
        local location loc1
        local location loc2
        
        
        if phase != 2 and GetWidgetLife(caster) > 0.405 then
            if phase == 0 then
                set real1 = LoadReal( hash , ID , StringHash("angleSide") )
                set real2 = real1 - bj_PI
                set real3 = LoadReal( hash , ID , StringHash("sideOffset") ) + WIDTHSPEED
                set real4 = LoadReal( hash , ID , StringHash("x") )
                set real5 = LoadReal( hash , ID , StringHash("y") )
                if real3 >= FENCEWIDTH then
                    set real3 = FENCEWIDTH
                    call SetUnitX( u , real4 + real3 * Cos(real1) )
                    call SetUnitY( u , real5 + real3 * Sin(real1) )
                    call SetUnitX( other , real4 + real3 * Cos(real2) )
                    call SetUnitY( other , real5 + real3 * Sin(real2) )
                    call SetUnitVertexColor( u , 255 , 255 , 255 , 255 )
                    call SetUnitVertexColor( other , 255 , 255 , 255 , 255 )
                    call SetLightningColor( l , 1. , 1. , 1. , 1. )
                    call SaveInteger( hash , ID , StringHash("phase") , 1 )
                else
                    call SetUnitX( u , real4 + real3 * Cos(real1) )
                    call SetUnitY( u , real5 + real3 * Sin(real1) )
                    call SetUnitX( other , real4 + real3 * Cos(real2) )
                    call SetUnitY( other , real5 + real3 * Sin(real2) )
                    set i = LoadInteger( hash , ID , StringHash("alpha") ) + LoadInteger( hash , ID , StringHash("visiSpeed") )
                    call SetUnitVertexColor( u , 255 , 255 , 255 , i )
                    call SetUnitVertexColor( other , 255 , 255 , 255 , i )
                    call SetLightningColor( l , 1. , 1. , 1. , I2R(i) / 255 )
                    call SaveInteger( hash , ID , StringHash("alpha") , i )
                    call SaveReal( hash , ID , StringHash("sideOffset") , real3 )
                endif
                set loc1 = GetUnitLoc(u)
                set loc2 = GetUnitLoc(other)
                call MoveLightningEx( l , true , GetUnitX(u) , GetUnitY(u) , GetLocationZ(loc1) + GetUnitFlyHeight(u) , GetUnitX(other) , GetUnitY(other) , GetLocationZ(loc2) + GetUnitFlyHeight(other) )
                call RemoveLocation(loc1)
                call RemoveLocation(loc2)
            else
                // Changes the the flying height of the balls
                set real1 = LoadReal( hash , ID , StringHash("phase1") )
                set real2 = LoadReal( hash , ID , StringHash("phase2") )
                call SetUnitFlyHeight( u , AVGHEIGHT + AVGHEIGHT / 2 * Sin(real1) , 0. )
                call SetUnitFlyHeight( other , AVGHEIGHT + AVGHEIGHT / 2 * Sin(real2) , 0. )
                call SaveReal( hash , ID , StringHash("phase1") , real1 + FHCHANGE )
                call SaveReal( hash , ID , StringHash("phase2") , real2 + FHCHANGE )
                
                set re8 = LoadReal( hash , ID , StringHash("angle") )
                set real2 = GetUnitX(u) + SPEED * Cos(re8)
                set real3 = GetUnitY(u) + SPEED * Sin(re8)

                set real1 = re8 - bj_PI / 2
                set real4 = real2 + 2 * FENCEWIDTH * Cos(real1)
                set real5 = real3 + 2 * FENCEWIDTH * Sin(real1)
                
                call SetUnitX( u , real2 )
                call SetUnitY( u , real3 )
                call SetUnitX( other , real4 )
                call SetUnitY( other , real5 )
                
                set loc1 = Location( real2 , real3 )
                set loc2 = Location( real4 , real5 )
                call MoveLightningEx( l , true , real2 , real3 , GetLocationZ(loc1) + GetUnitFlyHeight(u) , real4 , real5 , GetLocationZ(loc2) + GetUnitFlyHeight(other) )
                call RemoveLocation(loc1)
                call RemoveLocation(loc2)
                
                // Lower left corner
                set real1 = re8 + 3*bj_PI/4
                set real5 = SquareRoot(RECTOFFSET*RECTOFFSET*2)
                set re1 = real2 + real5 * Cos(real1)
                set re2 = real3 + real5 * Sin(real1)
                // Upper left corner
                set real1 = re8 + bj_PI/4
                set re3 = real2 + real5 * Cos(real1)
                set re4 = real3 + real5 * Sin(real1)
                // Lower right corner
                set real1 = re8 - bj_PI/2
                set re5 = re1 + 2 * ( FENCEWIDTH + RECTOFFSET ) * Cos(real1)
                set re6 = re2 + 2 * ( FENCEWIDTH + RECTOFFSET ) * Sin(real1)
                
                set bj_lastCreatedGroup = LoadGroupHandle( hash , ID , StringHash("group") )
                set plr = GetOwningPlayer(caster)
                set un = caster
                set re7 = LoadReal( hash , ID , StringHash("damage") )
                call GroupEnumUnitsInRange( grp , re1 , re2 , 2.5 * FENCEWIDTH , function UnitFilter ) 
                call GroupClear(grp)
                
                set real1 = LoadReal( hash , ID , StringHash("distance") )
                if real1 < DISTMAX then
                    call SaveReal( hash , ID , StringHash("distance") , real1 + SPEED )
                else
                    call DestroyGroup(bj_lastCreatedGroup)
                    call SaveInteger( hash , ID , StringHash("phase") , 2 )
                endif
            endif
        else
            if GetWidgetLife(caster) > 0.405 then
                set un = caster
                set plr = GetOwningPlayer(caster)
                set re1 = LoadReal( hash , ID , StringHash("damageAOE") )

                call GroupEnumUnitsInRange( grp , GetUnitX(u) , GetUnitY(u) , AOE , function UnitFilterExplode ) 
                call GroupClear(grp)
                
                call GroupEnumUnitsInRange( grp , GetUnitX(other) , GetUnitY(other) , AOE , function UnitFilterExplode ) 
                call GroupClear(grp)
            endif
            call UnitApplyTimedLife( u , 1 , 0.01 )
            call UnitApplyTimedLife( other , 1 , 0.01 )
            call DestroyLightning(l)
            call GroupRemoveUnit( ballGroup , u )
            call FlushChildHashtable( hash , ID )
            
            set balls = balls - 1
            if balls == 0 then
                call PauseTimer(ballTimer)
            endif
        endif
        
        set l = null
        set loc1 = null
        set loc2 = null
        set u = null
        set other = null
        set caster = null
    endfunction
    
    
    private function ballTimerExpire takes nothing returns nothing
        call ForGroup( ballGroup , function ballLoop )
    endfunction
    

    private function SF_Actions takes nothing returns nothing
        local unit u = GetTriggerUnit()
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local real facing = GetUnitFacing(u)
        local location loc = GetUnitLoc(u)
        local integer level = GetUnitAbilityLevel( u , ABILID ) - 1
        local integer ID
        
        local real rnd = GetRandomReal( 0 , 2 * bj_PI )
        set bj_lastCreatedUnit = CreateUnit( Player(15) , DUMMYID , x , y , facing )
        set ID = GetHandleId(bj_lastCreatedUnit)
        call GroupAddUnit( ballGroup , bj_lastCreatedUnit )
        call SetUnitExploded( bj_lastCreatedUnit , true )
        call SetUnitFlyHeight( bj_lastCreatedUnit , AVGHEIGHT , 0. )
        call SetUnitFlyHeight( bj_lastCreatedUnit , AVGHEIGHT + AVGHEIGHT / 2 * Sin(rnd) , 0. )
        call SetUnitVertexColor( bj_lastCreatedUnit , 255 , 255 , 255 , VISIBILITY )
        call SaveReal( hash , ID , StringHash("phase1") , rnd )
        
        set rnd = GetRandomReal( 0 , 2 * bj_PI )
        set bj_lastCreatedUnit = CreateUnit( Player(15) , DUMMYID , x , y , facing )
        call SetUnitExploded( bj_lastCreatedUnit , true )
        call SetUnitFlyHeight( bj_lastCreatedUnit , AVGHEIGHT , 0. )
        call SetUnitFlyHeight( bj_lastCreatedUnit , AVGHEIGHT + AVGHEIGHT / 2 * Sin(rnd) , 0. )
        call SetUnitVertexColor( bj_lastCreatedUnit , 255 , 255 , 255 , VISIBILITY )
        call SaveReal( hash , ID , StringHash("phase2") , rnd )
        
        set bj_lastCreatedLightning = AddLightningEx( LIGHTNINGTYPE , true , x , y , GetLocationZ(loc) + AVGHEIGHT , x + 1 , y + 1 , GetLocationZ(loc) + AVGHEIGHT )
        call SetLightningColor( bj_lastCreatedLightning , 1 , 1 , 1 , VISIBILITY )
        
        call SaveReal( hash , ID , StringHash("x") , x )
        call SaveReal( hash , ID , StringHash("y") , y )
        call SaveReal( hash , ID , StringHash("angle") , facing * bj_DEGTORAD )
        call SaveReal( hash , ID , StringHash("sideOffset") , 0. )
        call SaveReal( hash , ID , StringHash("angleSide") , (facing + 90) * bj_DEGTORAD )
        call SaveReal( hash , ID , StringHash("damage") , DMG + DMGBONUS * level )
        call SaveReal( hash , ID , StringHash("damageAOE") , DMGAOE + DMGBONUSAOE * level )
        call SaveUnitHandle( hash , ID , StringHash("caster") , u )
        call SaveUnitHandle( hash , ID , StringHash("other") , bj_lastCreatedUnit )
        call SaveInteger( hash , ID , StringHash("alpha") , VISIBILITY )
        call SaveInteger( hash , ID , StringHash("visiSpeed") , R2I(I2R(255-VISIBILITY) / ( FENCEWIDTH / WIDTHSPEED )) )
        call SaveLightningHandle( hash , ID , StringHash("l") , bj_lastCreatedLightning  )
        call SaveGroupHandle( hash , ID , StringHash("group") , CreateGroup() )
        
        set balls = balls + 1
        if balls == 1 then
            call TimerStart( ballTimer , TIMEOUT , true , function ballTimerExpire )
        endif
        
        call RemoveLocation(loc)
        set u = null
    endfunction
    
    private function SF_Conditions takes nothing returns boolean
        return GetSpellAbilityId() == ABILID
    endfunction
    

    private function InitTrig_StaticFence takes nothing returns nothing
        local trigger t = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( t , EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( t , Condition( function SF_Conditions ) )
        call TriggerAddAction( t , function SF_Actions )
        set PATH_ITEM = CreateItem( ITEMID , 0 , 0 )
        call SetItemVisible( PATH_ITEM , false )
    endfunction

endscope

xokelat, update the IsPointInRect to this:

JASS:
library PointInRect

    // Returns a boolean that tells whether the point is inside a rectangle.
    // (px , py) = Point to check
    // (cx , cy) = lower left corner of the rect
    // (ax , ay) = upper left corner
    // (bx , by) = lower right corner
    function IsPointInRect takes real px , real py , real cx , real cy , real ax , real ay , real bx , real by returns boolean        
        local real dot1 = (px-cx)*(ax-cx) + (py-cy)*(ay-cy)
        local real dot2 = (ax-cx)*(ax-cx) + (ay-cy)*(ay-cy)
        local real dot3 = (px-cx)*(bx-cx) + (py-cy)*(by-cy)
        local real dot4 = (bx-cx)*(bx-cx) + (by-cy)*(by-cy)
        
        return dot1 >= 0 and dot1 <= dot2 and dot3 >= 0 and dot3 <= dot4
    endfunction
    
endlibrary
 
Maker,

Instead of StringHash("x"), StringHash("y") you could easily do:

JASS:
private constant function HashX takes nothing returns integer
    return 1
endfunction

private constant function HashY takes nothing returns integer
    return 2
endfunction

That is, with a unique integer id for each different hash. This prevents having to constantly process the same strings.
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
I could just use call SaveReal(hash , id , 0 , x) , set x = LoadReal(hash , id , 0). That would be the optimal solution as far as hashtables go, right?

I mainly use hashed strings so I remember what they do. What you are saying that with using functions like in your example I can see what they are for from the function name, but improve performance by using "straight" integers.
 
Top