• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

DD Universal Pack v5.1c

This pack contains many different type of spells.


Coded in Warcraft 3 v1.30, JNGP is no longer needed.

This works with my edited libraries which are now in the map itself, you will need to copy and paste the library to your map once for all spells to work.





v1 - First release with 3 spells:
- Slash Strike
- Electric Field
- Dark Torture


v2 - Few fixes + better test map + 1 new spell
- Frost Eruption


v3 - An extreme updata to my spell pack
- Heavy improved test map
- Fixed 'Handle Stack Corruption'
- Improved performances of all spells
- Added 4 new spells
- Shadow Crossing
- Algid Aura
- Nature Blessing
- Water Exhausting


v3b - Additional update to v3
- Fixed bug with Slash Strike
- Fixed bug with Nature Blessing
- Improved performances of Nature Blessing
- Made tooltips on Shadow Crossing and Dark Torture more readable


v4 - Fixed old rare bugs which i found out!
- Used my librarys on almost all spells
- Spells are now faster and less leakless (groupex)
- Added 3 new spells (4 spell was lost by me loosing electricity and all stuff was not saved...)
- Instinct Flash
- Terror Blade
- Black Magic


v4b - Made spells stable to work with default JNGP
- Fixed some minor and big bugs


v4c - Fixed more bugs
- Recompiled map in non-debug mode (forgot in v4b...)
- Used suggestions by Dr. Boom
- Fixed green buff in Water Exhausting
- Made Frost Eruption be based on Channel ability and give "target image"
- Some odd lag fixed...


v4d - Spells where broken for a long time now, so this update primarely fixes that
- Some code changes in library and spells
- Volume of sounds are now user configurable
- Fixed bug when sound fail to preload, thous sounds do not play when first casted
Sounds are now propertly preloaded


v4e - Fixed bug with Electric Field, when heros are killed they cant be revived. Now they can be revived.

v5 - Recoded many spells and made them compatible with new DD Library 1.2
- Electrolix Zap - Frost Eruption
- Frostmourne Impale - Nature Blessing
- Instinct Flash - Algid Aura


v5.1 - Recoded many spells and made them compatible with new DD Library and WC3 Patch v1.30
- Added new spells:
- Terror Blade
- Summon Skeletons
- Bubble Blast


v5.1b - Fixed desync sound bug

v5.1c - Added channel version of 'Summon Skeletons' spell requested by hemmedo






Electrolix Zap

Calls for a bolts of lightning down from the sky to strike any enemy unit, dealing damage. Any unit that gets killed by this ability will be burned with lighting. The other units will get purged.


JASS:
[/B]
//TESH.scrollpos=33
//TESH.alwaysfold=0
/*
 **********************************************************************************************************
 
          Installation:
  
  1) Copy DD Library to your map
  2) Copy ElectrolixZap abilities (hero and dummy versions) to your map
  3) Export and Import 'thunder1.wav' sound from this map to yours
  4) Export and Import 'Great Lightning.mdx' models from this map to yours
  5) Copy this trigger to your map and modify it to your liking below
  6) Made on Warcraft III v1.30
 
 **********************************************************************************************************
*/

//! zinc
library ElectrolixZap requires DDLib
{

 // *******************************************************************************
 
 // * Ability Id found in object editor
 // Default:  'elfd'
 constant integer    ABILITY_ELECTROLIX_ZAP        = 'elfd';
 
 // * Sound file being played when spell is cast
 // Default: "Custom\\Ambient\\thunder1.wav"
 constant  string     SOUND_THUNDER           = "Custom\\Ambient\\thunder1.wav";
 // Default: 100.
 constant  real     SOUND_THUNDER_VOL         = 100.;
 // Default: 3500.
 constant real    SOUND_MAX_DISTANCE         = 3500.;
 
 // * Should camera shake when spell is cast
 constant boolean    USE_CAMERA_NOISE         = true;
 // Default: 2.5
 constant real    CAMERA_NOISE_DURATION        = 2.5;
 
 // * Should terrain deformation happen?
 constant boolean    USE_TERRAIN_DEFORM         = true;
 // Default: 200.
 constant  real     TERRAIN_DEFORM_DEPTH         = 200.;
 // Default: 1.
 constant  real     TERRAIN_DEFORM_DURATION        = 1.;
 
 // * Primary lightning strike effect created during initial spell cast
 // Default: "Lightning\\Great Lightning.mdl"
 constant  string     EFFECT_GREAT_LIGHTNING         = "Lightning\\Great Lightning.mdx";
 constant  real     EFFECT_GREAT_LIGHTNING_SIZE       = 1.2;
 constant  real     EFFECT_GREAT_LIGHTNING_ANIMATION_SPEED    = 50.;
 
 // * Secondary lightning bolts created during initial spell cast
 // Default: "Doodads\\Cinematic\\Lightningbolt\\Lightningbolt.mdx"
 constant  string     EFFECT_LIGHTING_BOLT         = "Doodads\\Cinematic\\Lightningbolt\\Lightningbolt.mdx";
 // Default: 1.
 constant  real     EFFECT_LIGHTING_BOLT_SIZE       = 1.;
 // Default: 200.
 constant  real     EFFECT_LIGHTING_BOLT_ANIMATION_SPEED    = 200.;
 // Default: 25
 constant  integer    NUMBER_OF_LIGHTINING_BOLTS       = 25;
 // Default: 0.15 seconds
 constant  real     LIGHTNING_BOLT_STRIKE_INTERVAL       = 0.15;
 // Default: "Doodads\\LordaeronSummer\\Props\\SmokeSmudge\\SmokeSmudge0.mdl"
 constant  string     EFFECT_LIGHTING_BOLT_SMOKE_MODEL_1     = "Doodads\\LordaeronSummer\\Props\\SmokeSmudge\\SmokeSmudge0.mdl";
 // Default: ""
 constant  string     EFFECT_LIGHTING_BOLT_SMOKE_MODEL_2     = "";//"Doodads\\LordaeronSummer\\Props\\SmokeSmudge\\SmokeSmudge1.mdl";
 // Default: ""
 constant  string     EFFECT_LIGHTING_BOLT_SMOKE_MODEL_3     = "";//"Doodads\\LordaeronSummer\\Props\\SmokeSmudge\\SmokeSmudge2.mdl";
 // Default: 1.2
 constant  real     EFFECT_LIGHTING_BOLT_SMOKE_MODEL_SIZE    = 1.2;
 // Default: 20.
 constant  real     EFFECT_LIGHTING_BOLT_SMOKE_MODEL_Z_OFFSET   = 20.;
 // Default: 15.
 constant  real     EFFECT_LIGHTING_BOLT_SMOKE_MODEL_DURATION   = 15.;
 
 
 // * After initial primary and secondary bolts, wait for a while before damaging units
 constant real    THUNDER_DAMAGE_DELAY        = 0.6;
 
 // * Dealing damage and summon shield/lightning on targets
 // Default: "Abilities\\Spells\\Orc\\LightningShield\\LightningShieldTarget.mdx"
 constant  string     EFFECT_LIGHTNING_UNIT_ZAP        = "Abilities\\Spells\\Orc\\LightningShield\\LightningShieldTarget.mdx";
 
 // * Load dummies and shock target with forked lightning, add thunder clap effect and purge
 // Default: 'efef'
 constant  integer    ABILITY_DUMMY_ELECTRIC_SHOCK       = 'efef';
 // Default: 1000.
 constant real    DUMMY_LIGHTNING_HEIGHT        = 1000.;
 // Default: "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdx"
 constant  string     EFFECT_DUMMY_ELECTRIC_SHOCK       = "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdx";
 // Deafault: 'Apg2'
 constant  integer    ABILITY_DUMMY_PURGE         = 'Apg2';
 
 // * Upon unit dying change its color and animation speed
 constant integer    COLOR_LIGHTNING_BURN_RED       = 00;
 constant integer    COLOR_LIGHTNING_BURN_GREEN       = 00;
 constant integer    COLOR_LIGHTNING_BURN_BLUE       = 00;
 constant real    COLOR_LIGHTNING_BURN_FADE_DURATION     = 5.;
 constant real    LIGHTNING_BURN_ANIMATION_SPEED      = .75;
 
 
 // * When unit gets burned, he gets 'ELECTRIFY_SFX' effect on him
 constant integer    ELECTRIFY_COUNT          = 4;
 constant real    ELECTRIFY_INTERVAL         = .66;
 constant string    ELECTRIFY_SFX          = "Abilities\\Weapons\\Bolt\\BoltImpact.mdx";
 
 
 
 // ==============================================================================================================================================
 // * Level data
 
 function InitElectrolixZapLevelData() {
  // * This is AOE (Area of Effect)/(radius) per level
  // Default 1: 610
  // Default 2: 660
  // Default 3: 705
  ELECTROLIX_ZAP_AOE[01]     = 610.;
  ELECTROLIX_ZAP_AOE[02]     = 660.;
  ELECTROLIX_ZAP_AOE[03]     = 705.;
  
  // This is damage to target per level
  // Default 1: 125
  // Default 2: 260
  // Default 3: 400
  ELECTROLIX_ZAP_DAMAGE[01]    = 125.;
  ELECTROLIX_ZAP_DAMAGE[02]    = 260.;
  ELECTROLIX_ZAP_DAMAGE[03]    = 400.;
  
  // This is the max damage spell can deal to all units
  // Default 1: 1000
  // Default 2: 2100
  // Default 3: 3250
  ELECTROLIX_ZAP_MAX_DAMAGE[01]   = 1000.;
  ELECTROLIX_ZAP_MAX_DAMAGE[02]   = 2100.;
  ELECTROLIX_ZAP_MAX_DAMAGE[03]  = 3250.;
 }
 
 
 //***********************************************************************
 //                    Main Unit Group Filter
 function ElecutixZapGroupFilter(unit f, player caster) -> boolean {
  return !IsUnitType(f, UNIT_TYPE_DEAD)    &&
      !IsUnitType(f, UNIT_TYPE_STRUCTURE)   &&
      !IsUnitType(f, UNIT_TYPE_MAGIC_IMMUNE) &&
      !IsUnitType(f, UNIT_TYPE_MECHANICAL)  &&
      IsUnitEnemy(f, caster)      &&
      IsUnitVisible(f, caster)     &&
      !DDIsUnitWard(f)       &&
      !BlzIsUnitInvulnerable(f);
 }
 
 // *******************************************************************************
 // *    Spell other variables (non-modifiable)
 // *******************************************************************************
 
 type smokecluster extends effect[NUMBER_OF_LIGHTINING_BOLTS];
 
 effect    LastLigBolt   = null;
 real   ELECTROLIX_ZAP_AOE[];
 real   ELECTROLIX_ZAP_DAMAGE[];
 real   ELECTROLIX_ZAP_MAX_DAMAGE[];
 smokecluster pSmokeGroup[];
 
 struct ezdata {
  unit u;
  real aoe;
  player owner;
  real x, y;
  real mxDmg, dmg;
  effect e[64];
  integer i=00;
  group g, dg;
   
  static thistype Temp  = p_null;
 }
 
 struct dmgdelay {
  unit u, f;
  real dmg;
  integer n;
 }
 
 struct unitfade {
  unit u;
  real r, g, b;
  real vr, vg, vb;
  boolean burn=false;
  
  static unitfade pUF[];
 }
 
 function RawDamage2Damage(unit u, real dmg) -> real {
  if (IsUnitType(u, UNIT_TYPE_HERO)) {
   if (UnitHasItemOfTypeBJ(u, 'brac'))
    return dmg*.5;
   return dmg*.75;
  }
  return dmg;
 }
 
 //===========================================================================
 // Main init electric field function
 function onInit() {
  //--------------------->
  //* Load init locals
  //<--------------------
  trigger   t = CreateTrigger();
  
  // *** Initialize constants
  InitElectrolixZapLevelData();
  
  
  // ###############################################################
        TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT);
        TriggerAddCondition(t, Condition(function() -> boolean {
   real   x = GetSpellTargetX(), y = GetSpellTargetY();
   unit   u = GetTriggerUnit();
   integer   lvl = GetUnitAbilityLevel(u, GetSpellAbilityId());
   integer   i;
   sound    s;
   real   d;
   p_real   pr;
   effect   e;
            ezdata          ezd;
  
   if (GetSpellAbilityId() != ABILITY_ELECTROLIX_ZAP)
    return false;

   
   // Play sound and shake camera for players within spell cast range
   DDGenericSound(SOUND_THUNDER, SOUND_THUNDER_VOL, x, y, SOUND_MAX_DISTANCE, 1.);
   static if (USE_CAMERA_NOISE)
    DDCameraSetSourceNoiseForPlayers(x, y, 70., 1750., SOUND_MAX_DISTANCE, CAMERA_NOISE_DURATION);
   /*
   for (i=00; i < bj_MAX_PLAYERS; i+=01) {
    if (GetLocalPlayer() == Player(i)) {
     d = SquareRoot( Pw_2(GetCameraTargetPositionX()-x) + Pw_2(GetCameraTargetPositionY()-y) );
     if (d < SOUND_MAX_DISTANCE) {
      s = CreateSound(SOUND_THUNDER, false, false, false, 10, 10, "");
      SetSoundVolume(s, R2I(SOUND_THUNDER_VOL-d*(SOUND_THUNDER_VOL/SOUND_MAX_DISTANCE)));
      StartSound(s);
      KillSoundWhenDone(s);
      s = null;
      
      static if (USE_CAMERA_NOISE)
       CameraSetSourceNoise(70.-(d*(70./SOUND_MAX_DISTANCE)), 1750.-(d*(1750./SOUND_MAX_DISTANCE)));
     }
    }
   }
   
   static if (USE_CAMERA_NOISE)
    DDStartTim(CAMERA_NOISE_DURATION, false, p_null, function() {
     CameraSetSourceNoise(0., 0.);
    });
   
   */
   // * Terrain deformation crater action
   static if (USE_TERRAIN_DEFORM)
    TerrainDeformCrater(x, y, ELECTROLIX_ZAP_AOE[lvl], TERRAIN_DEFORM_DEPTH, R2I(TERRAIN_DEFORM_DURATION*1000.), false);
   
   // * Load main big thunder effect
   e = AddSpecialEffect(EFFECT_GREAT_LIGHTNING, x, y);
   BlzSetSpecialEffectScale(e, EFFECT_GREAT_LIGHTNING_SIZE);
   BlzSetSpecialEffectTimeScale(e, EFFECT_GREAT_LIGHTNING_ANIMATION_SPEED/100.);
   DestroyEffect(e); e = null;
   
   // * Load extra lightning effects
   if (NUMBER_OF_LIGHTINING_BOLTS > 00) {
    pr = p_real.create();
    pr[00] = Pow(ELECTROLIX_ZAP_AOE[lvl], 1.3333);//*ELECTROLIX_ZAP_AOE[lvl];
    pr[01] = x; pr[02] = y;
    
    pSmokeGroup[pr] = smokecluster.create();
    DDStartTim(EFFECT_LIGHTING_BOLT_SMOKE_MODEL_DURATION, false, pSmokeGroup[pr], function() {
     smokecluster sc = DDTimData();
     integer i;
     for(i=00; i < NUMBER_OF_LIGHTINING_BOLTS; i+=01) {
      DestroyEffect(sc[i]); sc[i] = null;
     }
     sc.destroy();
     DDQuitTim();
    });
    
    DDStartTim(LIGHTNING_BOLT_STRIKE_INTERVAL, true, pr, function() {
     p_real   pr     = DDTimData();
     real   r     = Pow( GetRandomReal(50., pr[00]), .75 );
     real   rad    = GetRandomReal(0., bj_PI*2.);
     effect   smoke;
     integer  smoke_rnd_n  = 00;
     real  x, y;
     
     DestroyEffect(LastLigBolt);
     if (DDTimTick() == NUMBER_OF_LIGHTINING_BOLTS) {
      LastLigBolt = null;
      pr.destroy();
      DDQuitTim();
      return;
     }
     
     if (EFFECT_LIGHTING_BOLT_SMOKE_MODEL_2 != "")
      smoke_rnd_n += 01;
     if (EFFECT_LIGHTING_BOLT_SMOKE_MODEL_3 != "")
      smoke_rnd_n += 01;
     smoke_rnd_n = GetRandomInt(00, smoke_rnd_n);
     
     x = pr[01] + r * Cos(rad); y = pr[02] + r * Sin(rad);
     LastLigBolt = AddSpecialEffect(EFFECT_LIGHTING_BOLT, x, y);
     BlzSetSpecialEffectScale(LastLigBolt, EFFECT_LIGHTING_BOLT_SIZE);
     BlzSetSpecialEffectTimeScale(LastLigBolt, EFFECT_LIGHTING_BOLT_ANIMATION_SPEED/100.);
     if (smoke_rnd_n == 00)
      smoke = AddSpecialEffect(EFFECT_LIGHTING_BOLT_SMOKE_MODEL_1, x, y);
     else if (smoke_rnd_n == 01)
      smoke = AddSpecialEffect(EFFECT_LIGHTING_BOLT_SMOKE_MODEL_2, x, y);
     else
      smoke = AddSpecialEffect(EFFECT_LIGHTING_BOLT_SMOKE_MODEL_3, x, y);
     BlzSetSpecialEffectScale(smoke, EFFECT_LIGHTING_BOLT_SMOKE_MODEL_SIZE);
     BlzSetSpecialEffectZ(smoke, DDTerrZ(x, y) + EFFECT_LIGHTING_BOLT_SMOKE_MODEL_Z_OFFSET);
     pSmokeGroup[pr][00] = smoke;
     pSmokeGroup[pr] += smokecluster(01);
    });
   }
  
   ezd = ezdata.create();
   ezd.u = u;
   ezd.aoe = ELECTROLIX_ZAP_AOE[lvl];
   ezd.owner = GetOwningPlayer(u);
   ezd.x = x; ezd.y = y;
   ezd.dmg = ELECTROLIX_ZAP_DAMAGE[lvl];
   ezd.mxDmg = ELECTROLIX_ZAP_MAX_DAMAGE[lvl];
   
   DDStartTim(THUNDER_DAMAGE_DELAY, false, ezd, function() {
    ezdata.Temp = DDTimData();
    ezdata.Temp.g = DDLoadGroup();
    
    GroupEnumUnitsInRange(ezdata.Temp.g, ezdata.Temp.x, ezdata.Temp.y, ezdata.Temp.aoe, Filter(function() -> boolean {
     ezdata ezd = ezdata.Temp;
     
     if ( ElecutixZapGroupFilter(GetFilterUnit(), ezd.owner) ) {
      // *  Do pre-damage so taht creeps dont run away from invulnerable dummy units
      if (GetPlayerController(GetOwningPlayer(GetFilterUnit())) == MAP_CONTROL_CREEP)
       IssuePointOrder(GetFilterUnit(), "attack", GetUnitX(ezd.u), GetUnitY(ezd.u));
      
      ezd.e[ezd.i] = AddSpecialEffectTarget(EFFECT_LIGHTNING_UNIT_ZAP, GetFilterUnit(), "origin");
      ezd.i += 01;
     }
     
     return true;
    }));
    
    ezdata.Temp.dg = DDLoadGroup();
    DDStartTim(THUNDER_DAMAGE_DELAY, false, ezdata.Temp, function() {
     ezdata ezd = DDTimData();
     ezdata.Temp = ezd;
     ezd.dmg = RMinBJ(ezd.mxDmg/ezd.i, ezd.dmg);
     
     ForGroup(ezd.g, function() {
      ezdata ezd = ezdata.Temp;
      unit u = GetEnumUnit();
      real x = GetUnitX(u), y = GetUnitY(u);
      real rad = GetRandomReal(0., bj_PI*2);
      real dist = GetRandomReal(225., 375.);
      unit d = DDLoadSpellDummy(ezd.owner, x + dist * Cos(rad), y + dist * Sin(rad), ABILITY_DUMMY_ELECTRIC_SHOCK, 01);
      real dmg;
      dmgdelay dd;
      
      ezd.i -= 01;
      DestroyEffect(ezd.e[ezd.i]);
      ezd.e[ezd.i] = null;
      
      if (IsUnitEnemy(u, ezd.owner) && !IsUnitType(u, UNIT_TYPE_DEAD)) {
       SetUnitFlyHeight(d, DUMMY_LIGHTNING_HEIGHT, 0.);
       IssueTargetOrder(d, "chainlightning", u);
       DestroyEffect(AddSpecialEffectTarget(EFFECT_DUMMY_ELECTRIC_SHOCK, u, "origin"));
      }
      
      // * if unit dies, then dummy cant cast spell on that unit
      GroupAddUnit(ezd.dg, d);
      dmg = RawDamage2Damage(u, ezd.dmg);
      dd = dmgdelay.create();
      dd.u = ezd.u; dd.f = u;
      dd.dmg = dmg;
      dd.n = ELECTRIFY_COUNT;
      DDStartTim(.2, false, dd, function() {
       dmgdelay dd = DDTimData();
       unitfade uf;
       
       if (IsUnitEnemy(dd.f, GetOwningPlayer(dd.u)) && !IsUnitType(dd.f, UNIT_TYPE_DEAD)) {
        UnitDamageTarget(dd.u, dd.f, dd.dmg, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_UNKNOWN, null);
        
        SetUnitVertexColor(dd.f, COLOR_LIGHTNING_BURN_RED, COLOR_LIGHTNING_BURN_GREEN, COLOR_LIGHTNING_BURN_BLUE, 255);
        SetUnitTimeScale(dd.f, LIGHTNING_BURN_ANIMATION_SPEED);
        DDStartTim(ELECTRIFY_INTERVAL, true, dd, function() {
         dmgdelay dd = DDTimData();
         
         DestroyEffect(AddSpecialEffectTarget(ELECTRIFY_SFX, dd.f, "origin"));
         
         dd.n -= 01;
         if (dd.n == 00) {
          dd.destroy();
          DDQuitTim();
         }
        });
        
        if (!IsUnitType(dd.f, UNIT_TYPE_DEAD)) {
         uf = unitfade.pUF[H2ID(dd.f)];
         if (uf == p_null) {
          uf = unitfade.create();
          uf.u = dd.f;
          unitfade.pUF[H2ID(dd.f)] = uf;
          
          DDStartTim(DD_INTERVAL, true, uf, function() {
           unitfade uf = DDTimData();
           
           uf.r += uf.vr;
           uf.g += uf.vg;
           uf.b += uf.vb;
           
           SetUnitVertexColor(uf.u, R2I(255.*Pw_2(uf.r)), R2I(255.*Pw_2(uf.g)), R2I(255.*Pw_2(uf.b)), 255);
           
           if (uf.r > 1. || uf.burn) {
            if (uf.burn)
             SetUnitVertexColor(uf.u, COLOR_LIGHTNING_BURN_RED, COLOR_LIGHTNING_BURN_GREEN, COLOR_LIGHTNING_BURN_BLUE, 255);
            else
             SetUnitTimeScale(uf.u, 1.);
            unitfade.pUF[H2ID(uf.u)] = p_null;
            uf.u = null;
            uf.destroy();
            DDQuitTim();
           }
           
          });
         }
         
         uf.r = COLOR_LIGHTNING_BURN_RED / 255.;
         uf.g = COLOR_LIGHTNING_BURN_GREEN / 255.;
         uf.b = COLOR_LIGHTNING_BURN_BLUE / 255.;
         uf.vr = DD_INTERVAL * (1.-uf.r) / COLOR_LIGHTNING_BURN_FADE_DURATION;
         uf.vg = DD_INTERVAL * (1.-uf.g) / COLOR_LIGHTNING_BURN_FADE_DURATION;
         uf.vb = DD_INTERVAL * (1.-uf.b) / COLOR_LIGHTNING_BURN_FADE_DURATION;
        } else if (IsUnitType(dd.f, UNIT_TYPE_HERO)) {
         SetUnitVertexColor(dd.f, 255, 255, 255, 255);
        } else if (unitfade.pUF[H2ID(dd.f)] != p_null)
         unitfade.pUF[H2ID(dd.f)].burn = true;
       } else
        dd.destroy();
       
       DDQuitTim();
      });
      
      d = null;
      u = null;
     });
     
     DDStartTim(.3, true, ezd, function() {
      ezdata.Temp = DDTimData();
      
      // First run, wait for 1 x .3 secs
      if (DDTimTick() == 01) {
       ForGroup(ezdata.Temp.dg, function() {
        unit e = GetEnumUnit(), t = FirstOfGroup(ezdata.Temp.g);
        UnitRemoveAbility(e, ABILITY_DUMMY_ELECTRIC_SHOCK);
        UnitAddAbility(e, ABILITY_DUMMY_PURGE);
        SetUnitX(e, GetUnitX(t)); SetUnitY(e, GetUnitY(t));
        IssueTargetOrder(e, "purge", t);
        GroupRemoveUnit(ezdata.Temp.g, t);
        
        e = null; t = null;
       });
       return;
      }
      
      // Second run, wait for 2 x .3 secs
      ForGroup(ezdata.Temp.dg, function() {
       UnitRemoveAbility(GetEnumUnit(), ABILITY_DUMMY_PURGE);
       DDRecycleDummy(GetEnumUnit());
      });
      
      DDRecycleGroup(ezdata.Temp.g);
      DDRecycleGroup(ezdata.Temp.dg);
      ezdata.Temp.destroy();
      DDQuitTim();
     });
     
     DDQuitTim();
    });
    
    
    DDQuitTim();
   });
  
   return false;
  }));
 
        t = null;
    }
}
//! endzinc


[B]

Frostmourne Impale

Shoots a wave of dark blades which damage any unit who comes in range and when they are hit they will be drastically slowed for short amount of time.


JASS:
[/B]
//TESH.scrollpos=15
//TESH.alwaysfold=0
//**************************************************************************************
//                              Installation:
//
// - 1. Copy this trigger and "DD Library" to your map
// - 2. Go to Import Manager (F12) and extract BTNDarkTouch.blp and its DISBTN version
//      sword_create.wav, sword_disappere.wav, sword_cut.wav and sword_start.wav
//      Frostmourne.mdx and DarkRitualTarget.mdx
// - 3. Import all of this to your map and set ther path to as you can see here (in my map)
// - 4. Go to Object Manager (F6) and copy "Frostmourne Impale Slow(Dummy)" ability and
//      main hero ability "Frostmourne Impale". When you are pasting them to your map make sure you
//      match there rawcodes with ones below
// - 5. If you want different raw codes edit the below as well
// - 6. Made on Warcraft III v1.30
// - 7. Edit data below to your own will and enjoy the spell
//
//
//**************************************************************************************

//! zinc
library FrostmourneImpale requires DDLib
{

 // *****************************************************************************************
 //        === Main Data ===
 // *****************************************************************************************
 
    // This is the raw code of the spell 'Frostmourne Impale'
    // Default: 'Drkt'
    constant integer      ABILITY_FROSTMOURNE_IMPALE       = 'Drkt';
    // This is the raw code of the sword 'Unit'
    // Default: 'drks'
    //constant integer      DUMMY_SWORD_RAWCODE        = 'drks';
    // This is the raw code of 'Frostmourne Impale Slow (dummy)' ability
    // Default: 'dtsd'
    constant integer      DUMMY_SLOW_RAWCODE         = 'dtsd';
 // Issue order for 'DUMMY_SLOW_RAWCODE' ability
 // Default: "slow"
    constant string       DUMMY_SLOW_ISSUEORDER        = "slow";
 // How offten are swords created, one after another
    // Default: 0.2
    constant real       SWORD_CREATION_INTERVAL       = 0.2;
 // Distance from caster and closest sword
 // Default: 250.
    constant real       SWORD_CREATION_OFFSET_FROM_CASTER    = 250.;
 // Distance from sword to sword
 // Default: 70.
    constant real       SWORD_CREATION_OFFSET_FROM_SWORD    = 70.;
 // Time it takes for sword to launch
 // Default: 1.
 constant real      SWORD_CREATE_LAUNCH_DURATION     = 1.;
 // Height of sword
 // Default: 110.
 constant real       SWORD_HEIGHT          = 110.;
 // Collision area around the sword, if units are found within it, they are hit
 // Default: 60.
 constant real       SWORD_COLLISION_SIZE       = 60.;
 // Sword creation start transparency / Sword disappear end transparency
 // Default: 00
 constant integer      SWORD_CREATE_START_ALPHA      = 00;
 // Sword creation end transparency / Sword disappear start transparency
 // Default: 255
 constant integer      SWORD_CREATE_END_ALPHA       = 255;
 // Time it takes for sword to appear
 // Default: 0.9
 constant real      SWORD_CREATE_FADE_DURATION      = .9;
 // Time it takes for sword to disappear
 // Default: 2.5
 constant real      SWORD_DISAPPEAR_DURATION      = 2.5;
 // Disappearing speed of sword
 // Default: 100.
 constant real      SWORD_DISAPPEAR_MOVE_SPEED      = 100.;
 
 // *****************************************************************************************
 //        === Effect ===
 // *****************************************************************************************
 
 // This is the file path to sword model
    // Default: "Spells\\FrostmourneImpale\\Frostmourne.mdx"
    constant string       SWORD_MODEL_PATH         = "Spells\\FrostmourneImpale\\Frostmourne.mdx";
 // This is size/scaling of sword
    // Default: 1.
    constant real       SWORD_MODEL_SIZE         = 1.;
    // This is trail effect missile of each sword
    // Default: "Abilities\\Weapons\\ZigguratMissile\\ZigguratMissile.mdl"
    constant string       SWORD_AFTER_EFFECT_SFX        = "Abilities\\Weapons\\ZigguratMissile\\ZigguratMissile.mdx";
 // Appear and disappear sfx on sword
 // Default: "Spells\\FrostmourneImpale\\DarkRitualTarget.mdx"
    constant string       SWORD_CREATE_SFX         = "Spells\\FrostmourneImpale\\DarkRitualTarget.mdx";
 // Trail effect and appear/disappear effect height
 // Default: 60.
    constant real       SWORD_CREATE_SFX_HEIGHT       = 60.;
 // Trail effect and appear/disappear effect size
 // Default: 0.4
    constant real       SWORD_CREATE_SFX_SIZE        = .4;
 
    // Blood effect upon sword hit
    // Default: "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl"
    constant string       BLOOD_EFFECT          = "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl";
 
 // *****************************************************************************************
 //        === Sound ===
 // *****************************************************************************************
 
 // Sound path of sword creation
    // Default: "Custom\\Spells\\Dark Torture\\sword_create.wav"
    constant string       SWORD_CREATE_SOUND_PATH       = "Custom\\Spells\\Frostmourne Impale\\sword_create.wav";
 constant real       SWORD_CREATE_SOUND_PATH_VOL      = 55.;
    // Sound path of sword launch
    // Default: "Custom\\Spells\\Dark Torture\\sword_start.wav"
    constant string       SWORD_SOUND_START_PATH        = "Custom\\Spells\\Frostmourne Impale\\sword_start.wav";
 constant real       SWORD_SOUND_START_PATH_VOL       = 80.;
    
    // Sound path of sword hiting the target
    // Default: "Custom\\Spells\\Dark Torture\\sword_hit.wav"
    constant string       SWORD_HIT_PATH          = "Custom\\Spells\\Frostmourne Impale\\sword_cut.wav";
 constant real       SWORD_HIT_PATH_VOL        = 70.;
    // Sound of swords disappearing
    // Default: "Custom\\Spells\\Dark Torture\\sword_disappere.wav"
    constant string       SWORD_DISAPPEAR_PATH        = "Custom\\Spells\\Frostmourne Impale\\sword_disappere.wav";
 constant real       SWORD_DISAPPEAR_PATH_VOL       = 70.;
 
 // This is max sound hear range
    // Default: 3500.
    constant real       SOUND_MAX_DISTANCE         = 3500.;
    
 // *****************************************************************************************
 //        === Level Data ===
 // *****************************************************************************************
 
 // --------------------------------------------------------------
    // This variables are not supposed to be modified here, modify them below in Setup function
    integer    MAX_SWORD_COUNT[];
    real     SWORD_MAX_TRAVEL_DISTANCE[];
    real     SINGLE_SWORD_DAMAGE[];
    real     SWORD_MOVE_SPEED[];
 // --------------------------------------------------------------

 // This part of code is used to define spell constants per level
 function FrostmourneImpale_Setup() {
  // Default: Level 1 = 8
  // Default: Level 2 = 9
  // Default: Level 3 = 10
  MAX_SWORD_COUNT[01] = 8;
  MAX_SWORD_COUNT[02] = 9;
  MAX_SWORD_COUNT[03] = 10;
  
  // Default: Level 1 = 125.
  // Default: Level 2 = 220.
  // Default: Level 3 = 300.
  SINGLE_SWORD_DAMAGE[01] = 125.;
  SINGLE_SWORD_DAMAGE[02] = 220.;
  SINGLE_SWORD_DAMAGE[03] = 300.;
  
  // Default: Level 1 = 1250.
  // Default: Level 2 = 1350.
  // Default: Level 3 = 1500.
  SWORD_MAX_TRAVEL_DISTANCE[01] = 1250.;
  SWORD_MAX_TRAVEL_DISTANCE[02] = 1350.;
  SWORD_MAX_TRAVEL_DISTANCE[03] = 1500.;
  
  // Default: Level 1 = 900.
  // Default: Level 2 = 1100.
  // Default: Level 3 = 1200.
  SWORD_MOVE_SPEED[01] = 900.;
  SWORD_MOVE_SPEED[02] = 1100.;
  SWORD_MOVE_SPEED[03] = 1200.;
 }
 
 // *****************************************************************************************
 //        === Unit Damage Filter  ===
 // *****************************************************************************************
 
 function FrostmourneImpaleUnitFilter(unit f, player owner) -> boolean {
  return !IsUnitType(f, UNIT_TYPE_STRUCTURE)   &&
      !IsUnitType(f, UNIT_TYPE_MECHANICAL)   &&
      !IsUnitType(f, UNIT_TYPE_DEAD)    &&
      !IsUnitType(f, UNIT_TYPE_MAGIC_IMMUNE)  &&
      !IsUnitType(f, UNIT_TYPE_FLYING)    &&
      !BlzIsUnitInvulnerable(f)     &&
      IsUnitEnemy(f, owner);
 }
 
 // ==========================================================================================
 //        *** Spell Code ***
 // ==========================================================================================
 
 struct sword {
  ddeffect s;
  player p;
  unit dmy;
  ddeffect trail;
  real x, y;
  real vx, vy;
  real dist, spd;
  integer lvl;
  group g;
  boolean disappear_off;
  
  static player Owner = null;
  
  static method create(real px, real py, real rad, player owner, integer abilLvl) -> thistype {
   thistype this = allocate();
   real tz = DDTerrZ(px, py);
   
   g = DDLoadGroup();
   s = ddeffect.createZ(SWORD_MODEL_PATH, px, py, SWORD_HEIGHT + tz, rad, SWORD_MODEL_SIZE);
   s.Fade(SWORD_CREATE_START_ALPHA/2.55, SWORD_CREATE_END_ALPHA/2.55, SWORD_CREATE_FADE_DURATION);
   p = owner;
   //s = CreateUnit(owner, DUMMY_SWORD_RAWCODE, px, py, rad*bj_RADTODEG);
   //SetUnitFlyHeight(s, SWORD_HEIGHT, 0.);
   lvl = abilLvl;
   x = px; y = py;
   vx = DD_INTERVAL * SWORD_MOVE_SPEED[lvl] * Cos(rad);
   vy = DD_INTERVAL * SWORD_MOVE_SPEED[lvl] * Sin(rad);
   dist = SWORD_MAX_TRAVEL_DISTANCE[lvl];
   spd = DD_INTERVAL*SWORD_MOVE_SPEED[lvl];
   disappear_off = true;
   trail = ddeffect.createZ(SWORD_AFTER_EFFECT_SFX, x, y, SWORD_HEIGHT + tz, rad, SWORD_CREATE_SFX_SIZE);
   
   DDGenericSound(SWORD_CREATE_SOUND_PATH, SWORD_CREATE_SOUND_PATH_VOL, px, py, SOUND_MAX_DISTANCE, 1.);
   //DDFadeUnit(s, SWORD_CREATE_START_ALPHA, SWORD_CREATE_END_ALPHA, SWORD_CREATE_FADE_DURATION);
   ddeffect.createZ(SWORD_CREATE_SFX, px, py, SWORD_CREATE_SFX_HEIGHT + tz, rad, SWORD_CREATE_SFX_SIZE).destroyx(SWORD_DISAPPEAR_DURATION);
   
   return this;
  }
  
  method SwordLaunch() {
   DDGenericSound(SWORD_SOUND_START_PATH, SWORD_SOUND_START_PATH_VOL, x, y, SOUND_MAX_DISTANCE, 1.);
   
   DDStartTim(DD_INTERVAL, true, this, function() {
    sword this = DDTimData();
    unit fg;
    
    x += vx; y += vy;
    s.Position(x, y);
    trail.Position(x, y);
    /*SetUnitX(s, x);
    SetUnitY(s, y);
    trail.X = x;
    trail.Y = y;*/
    
    if (g != null) {
     if (IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)) {
      DDRecycleGroup(g);
      dist = 0.;
      g = null;
      return;
     }
     
     Owner = p;
     GroupEnumUnitsInRange(g, x, y, SWORD_COLLISION_SIZE, Filter(function() -> boolean {
      return FrostmourneImpaleUnitFilter(GetFilterUnit(), Owner);
     }));
     
     fg = FirstOfGroup(g);
     if (fg != null) {
      dmy = DDLoadSpellDummy(Owner, x, y, DUMMY_SLOW_RAWCODE, 01);
      IssueTargetOrder(dmy, DUMMY_SLOW_ISSUEORDER, fg);
      UnitDamageTarget(dmy, fg, SINGLE_SWORD_DAMAGE[lvl], true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_METAL_HEAVY_STAB);
      DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT, fg, "origin"));
      DDGenericSound(SWORD_HIT_PATH, SWORD_HIT_PATH_VOL, x, y, SOUND_MAX_DISTANCE, 1.); 
      DDRecycleGroup(g);
      dist = 0.;
      g = null;
     }
     fg = null;
    }
    
    dist -= spd;
    if (dist < 0.) {
     if (disappear_off) {
      trail.destroy();
      trail = ddeffect.createZ(SWORD_CREATE_SFX, x, y, SWORD_CREATE_SFX_HEIGHT+DDTerrZ(x, y), trail.Facing, SWORD_CREATE_SFX_SIZE);
      //trail.Z = SWORD_HEIGHT;
      //trail.Pitch = 00;
      DDGenericSound(SWORD_DISAPPEAR_PATH, SWORD_DISAPPEAR_PATH_VOL, x, y, SOUND_MAX_DISTANCE, 1.);
      s.Fade(SWORD_CREATE_END_ALPHA/2.55, SWORD_CREATE_START_ALPHA/2.55, SWORD_DISAPPEAR_DURATION);
      //DDFadeUnit(s, SWORD_CREATE_END_ALPHA, SWORD_CREATE_START_ALPHA, SWORD_DISAPPEAR_DURATION);
      dist = SWORD_DISAPPEAR_MOVE_SPEED*SWORD_DISAPPEAR_DURATION;
      vx = DD_INTERVAL*SWORD_DISAPPEAR_MOVE_SPEED*vx/spd;
      vy = DD_INTERVAL*SWORD_DISAPPEAR_MOVE_SPEED*vy/spd;
      spd = DD_INTERVAL*SWORD_DISAPPEAR_MOVE_SPEED;
      disappear_off = false;
      
      if (g != null) {
       DDRecycleGroup(g);
       g = null;
      }
     } else {
      if (dmy != null) {
       UnitRemoveAbility(dmy, DUMMY_SLOW_RAWCODE);
       DDRecycleDummy(dmy);
       dmy = null;
      }
      trail.destroy();
      s.destroy();
      //RemoveUnit(s);
      //s = null;
      destroy();
      DDQuitTim();
     }
    }
   });
  }
 }
 
 struct data {
  unit u;
  real x, y;
  real tx, ty;
  integer lvl;
  real rad;
  real ox, oy;
  integer rnd_mx_n;
  integer rnd[32];
 }
 
 function onInit() {
  trigger t = CreateTrigger();
  
  FrostmourneImpale_Setup();
  
  TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT);
  TriggerAddCondition(t, Condition(function() -> boolean {
   data d;
   integer i;
   
   if (GetSpellAbilityId() != ABILITY_FROSTMOURNE_IMPALE)
    return false;
   
   d = data.create();
   d.u = GetTriggerUnit();
   d.x = GetWidgetX(d.u); d.y = GetWidgetY(d.u);
   d.tx = GetSpellTargetX(); d.ty = GetSpellTargetY();
   d.lvl = GetUnitAbilityLevel(d.u, ABILITY_FROSTMOURNE_IMPALE);
   d.rad = Atan2(d.y-d.ty, d.x-d.tx);
   d.ox = d.x + SWORD_CREATION_OFFSET_FROM_CASTER * Cos(d.rad);
   d.oy = d.y + SWORD_CREATION_OFFSET_FROM_CASTER * Sin(d.rad);
   d.rnd_mx_n = MAX_SWORD_COUNT[d.lvl];
   d.rad += bj_PI/2.;
   for(i=00; i < MAX_SWORD_COUNT[d.lvl]; i+=01) {
    d.rnd[i] = i-(MAX_SWORD_COUNT[d.lvl]/2);
   }
   
   DDStartTim(SWORD_CREATION_INTERVAL, true, d, function() {
    data d = DDTimData();
    sword s;
    integer rnd_n = GetRandomInt(00, d.rnd_mx_n-01);
    
    s = sword.create(d.ox + SWORD_CREATION_OFFSET_FROM_SWORD*d.rnd[rnd_n] * Cos(d.rad),
         d.oy + SWORD_CREATION_OFFSET_FROM_SWORD*d.rnd[rnd_n] * Sin(d.rad),
         (d.rad+(bj_PI/2)),
         GetOwningPlayer(d.u),
         d.lvl);
    
    DDStartTim(SWORD_CREATE_LAUNCH_DURATION, false, s, function() {
     sword(DDTimData()).SwordLaunch();
     DDQuitTim();
    });
    
    d.rnd_mx_n -= 01;
    d.rnd[rnd_n] = d.rnd[d.rnd_mx_n];
    
    if (d.rnd_mx_n == 00) {
     d.destroy();
     DDQuitTim();
    }
    
   });
   
   return false;
  }));
 }

}
//! endzinc
[B]

Frost Eruption

Sends an orb of frost at targt point, on landing explodes dealing damage and freezing all enemy ground units, while air units get slowed.


JASS:
//TESH.scrollpos=0
//TESH.alwaysfold=0
//**************************************************************************************
//                              Installation:
//
//
// - 1. Copy this trigger and DD Library to your map.
// - 2. Go to Import Manager (F12) and extract icons: BTNCRFrostShock.blp and its DISBTN version
//      sounds: fe_start.mp3, fe_explode1.mp3 and fe_explode2.mp3
//      Models: FrozenOrb.mdx, Frost2.mdx, FreezingRing.mdx, BlizzardEruption.mdx and (dummy.mdx -> if not from before)
// - 3. Import all of this to your map and set there path to as you can see here (in my map)
// - 4. Go to Object Manager (F6) and copy:
//      Air Freeze (Dummy) ability, Frost Eruption buff and
//      main ability Frost Eruption. When you are pasting them to your map make sure you
//      type the following rawcodes:
//      Frost Eruption:         'Feru'
//      Air Freeze (Dummy):     'Afre'
//      Frost Eruption {Buff}:  'Bfer'
// - 5. If you want different raw codes edit the below as well:
// - 6. Made on Warcraft III v1.30
// - 7. Edit data below to your own will and enjoy the spell:
//
//**************************************************************************************

//! zinc
library FrostEruption requires DDLib
{


    // The raw code of the spell Frost Eruption
    // Default: 'Feru'
    constant  integer    ABILITY_FROST_ERUPTION        = 'Feru';
 // This is scale / size of main orb
    // Default: 1.32
    constant  real     ORB_SCALE            = 1.32;
    constant  real     ORB_INITIAL_Z           = 70.;
    constant  real     ORB_MAX_HEIGHT           = 350.;
    constant  real     ORB_TRAVEL_TIME          = 2.;
 
    // With this ability air units are slowed
    // Default: 'Afre'
    constant  integer    ABILITY_AIR_FREEZE          = 'Afre';
    constant  integer    BUFF_AIR_FREEZE           = 'Bfer';
    // This is orb model path
    // Default: "Spells\\FrostEruption\\FrozenOrb.mdl"
    constant  string     ORB_MODEL_PATH           = "Spells\\FrostEruption\\FrozenOrb.mdx";
    // Main frost eruption effect
    // Default: "Spells\\FrostEruption\\BlizzardEruption.mdl"
    constant  string     ORB_ERUPTION_EFFECT         = "Spells\\FrostEruption\\BlizzardEruption.mdx";
 // Default: 2.
    constant  real     ORB_ERUPTION_EFFECT_SIZE       = 2.;
 // Default: 70.
    constant  real     ORB_ERUPTION_EFFECT_ANIMATION_SPEED     = 70.;
    // Frost Eruptions extra explosion effect
    // Default: "Spells\\FrostEruption\\FreezingRing.mdl"
    constant  string     ORB_EXPLOSION_EFFECT         = "Spells\\FrostEruption\\FreezingRing.mdx";
 // Default: 1.6
    constant  real     ORB_EXPLOSION_EFFECT_SIZE       = 1.6;
 // Default: 55.
    constant  real     ORB_EXPLOSION_EFFECT_ANIMATION_SPEED    = 55.;
    // Ground units freezed model path
    // Default: "Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathTargetArt.mdl"
    constant  string     FREEZE_EFFECT           = "Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathTargetArt.mdx";
    // This is orb's trail effect
    // Default: "Spells\\FrostEruption\\Frost2.mdx"
    constant  string     TRAIL_MODEL_PATH          = "Spells\\FrostEruption\\Frost2.mdx";
 // This is orb's trail effect size
    // Default: 1.
 constant  real     TRAIL_SCALE           = 1.;
    // Sound file on load (on spell cast)
    // Default: "Custom\\Spells\\Frost Eruption\\fe_start.mp3"
    constant  string     SPELL_START_SOUND          = "Custom\\Spells\\Frost Eruption\\fe_start.mp3";
 constant  real     SPELL_START_SOUND_VOL         = 75.;
 constant  real     SOUND_MAX_DISTANCE          = 3500.;
 
    // Sound file's on explosion
    // Default: "Custom\\Spells\\Frost Eruption\\fe_explode1.mp3"    
    constant  string     SPELL_EXPLODE_SOUND_1         = "Custom\\Spells\\Frost Eruption\\fe_explode1.mp3";
 constant  real     SPELL_EXPLODE_SOUND_VOL        = 75.; // Both 1 and 2 sounds volume
    // Default: "Custom\\Spells\\Frost Eruption\\fe_explode2.mp3"
    constant  string     SPELL_EXPLODE_SOUND_2         = "Custom\\Spells\\Frost Eruption\\fe_explode2.mp3";
    
    // Terrain deformation depth
    // Default: 180.
    constant  real     EXPLOSION_DEAPTH          = 180.;
    // Terrain deformatiob timeout
    // Default: 0.66
    constant  real     TERRAIN_DEFORMATION_DURATION       = 0.66;
    // Cameras power magnitude
    // Default: 20.
    constant  real     CAMERA_MAGNITUDE          = 20.;
 // Cameras power velocity
    // Default: 1800.
    constant  real     CAMERA_VELOCITY          = 1800.;
    // Camera noise duration
    // Default: 1.85
    constant  real     CAMERA_NOISE_DURATION         = 1.85;
    // How much time will orb need until reaching target point
    // Default: 1.5
    constant  real     ORB_DURATION           = 1.5;
 
 // Alter terrain upon explosion?
 // Default: true
 constant boolean    USE_TERRAIN_TYPE_MODIFICATION      = true;
 // Default: 'Iice'
    constant  integer    TERRAIN_TEXTURE_ID         = 'Iice';
 // Default: 01 / square
    constant  integer    TERRAIN_TEXTURE_SHAPE        = 01;
 // Default: 17
    constant  integer    TERRAIN_TEXTURE_VARIATIONS       = 17;
 // Default: 7.
    constant  real     TERRAIN_TEXTURE_DURATION       = 7.;
 
 
 
 
    
    // Do not edit this variables here edit then below
    real   FE_RADIUS[];
    real   FE_DAMAGE[];
    real   FE_MAX_DAMAGE[];
    real   FE_DURATION[];

 // Edit this to match your level data
 function SetupFrostEruption() {
  // Spells damage:
  // Default: 130 / 215 / 290
  FE_DAMAGE[01]    = 130.;
  FE_DAMAGE[02]    = 215.;
  FE_DAMAGE[03]    = 290.;
  
  // Spells radius:
  // Default: 500 / 515 / 540
  FE_RADIUS[01]    = 500.;
  FE_RADIUS[02]    = 515.;
  FE_RADIUS[03]    = 540.;
  
  // Spells max damage:
  // Default: 700 / 1300 / 1950
  FE_MAX_DAMAGE[01]   = 700.;
  FE_MAX_DAMAGE[02]   = 1300.;
  FE_MAX_DAMAGE[03]   = 1950.;
  
  // Spells ground units freeze duration:
  // Default: 4 / 4.5 / 5.25
  FE_DURATION[01]   = 4.;
  FE_DURATION[02]   = 4.5;
  FE_DURATION[03]   = 5.25;
 }

 // Main damage filter
 function FE_UnitFilter(unit f, player owner) -> boolean {
  return IsUnitEnemy(f, owner)        &&
      !IsUnitType(f, UNIT_TYPE_STRUCTURE)     &&
      !IsUnitType(f, UNIT_TYPE_MECHANICAL)    &&
      !IsUnitType(f, UNIT_TYPE_DEAD)     &&
      !BlzIsUnitInvulnerable(f)      &&
      !IsUnitType(f, UNIT_TYPE_MAGIC_IMMUNE);
 }
// ================================================================================
// ******                                                                   ******
//              Do not edit below if you don't know jass
// ******                                                                   ******
// ================================================================================
 
 constant integer TT_MAX_ARRAY = 64;
 
 struct terrtype {
  integer typ[TT_MAX_ARRAY], var[TT_MAX_ARRAY];
  boolean blighted[TT_MAX_ARRAY];
  real x, y, aoe;
  integer n=00;
  group g;
  
  static integer BlightAbilId[];
 }
 
 function ModifieTerrainType(real x, real y, real aoe, terrtype changeToTT) -> terrtype {
  real tx, ty, max_x;
  integer n=00;
  terrtype tt;
  
  if (changeToTT == p_null) {
   tt = terrtype.create();
   tt.g = DDLoadGroup();
   GroupEnumUnitsInRange(tt.g, x, y, aoe+960., function() -> boolean {
    unit u = GetFilterUnit();
    if (GetUnitAbilityLevel(u, 'Abgs') == 01) {
     terrtype.BlightAbilId[H2ID(u)] = 'Abgs';
     UnitRemoveAbility(u, 'Abgs');
     u = null;
     return true;
    } else if (GetUnitAbilityLevel(u, 'Abgl') == 01) {
     terrtype.BlightAbilId[H2ID(u)] = 'Abgs';
     UnitRemoveAbility(u, 'Abgl');
     u = null;
     return true;
    }
    u = null;
    return false;
   });
   
   tt.x = x; tt.y = y; tt.aoe = aoe;
   for(ty=-aoe; ty < aoe; ty+=bj_CELLWIDTH) {
    max_x = SquareRoot((aoe*aoe) - (ty*ty));
    for(tx=-max_x; tx < max_x; tx+=bj_CELLWIDTH) {
     tt.blighted[tt.n] = IsPointBlighted(x+tx, y+ty);
     if (!(tt.blighted[tt.n])) {
      tt.typ[tt.n] = GetTerrainType(x+tx, y+ty);
      tt.var[tt.n] = GetTerrainVariance(x+tx, y+ty);
     } else
      SetBlightPoint(Player(00), x+tx, y+ty, false);
     tt.n += 01;
     SetTerrainType(x+tx, y+ty, TERRAIN_TEXTURE_ID, GetRandomInt(00, TERRAIN_TEXTURE_VARIATIONS), 01, TERRAIN_TEXTURE_SHAPE);
    }
   }
   return tt;
  }
  
  tt = changeToTT;
  x = tt.x; y = tt.y; aoe = tt.aoe;
  for(ty=-aoe; ty < aoe; ty+=bj_CELLWIDTH) {
   max_x = SquareRoot((aoe*aoe) - (ty*ty));
   for(tx=-max_x; tx < max_x; tx+=bj_CELLWIDTH) {
    if (!(tt.blighted[n]))
     SetTerrainType(x+tx, y+ty, tt.typ[n], tt.var[n], 01, TERRAIN_TEXTURE_SHAPE);
    else
     SetBlightPoint(Player(00), x+tx, y+ty, true);
    n += 01;
   }
  }
  
  ForGroup(tt.g, function() {
   unit u = GetEnumUnit();
   UnitAddAbility(u, terrtype.BlightAbilId[H2ID(u)]);
   u = null;
  });
  DDRecycleGroup(tt.g);
  tt.destroy();
  return p_null;
 }
 
 // --------------------------------------------------------------------------------------------
 
 effect   FBEffect[];

 struct orb {
  ddeffect o, ot;
  real vx, vy, tz;
  real dist, mxDist, a;
  real spd;
  integer lvl;
  player owner;
  unit u;
  real dmg;
  group g;
  unit dmy;
  integer cnt=00;
  terrtype tt;
  
  static method create(unit u, real x, real y, real tx, real ty, player owner, integer lvl) -> thistype {
   thistype this = allocate();
   
   real rad = Atan2(ty-y, tx-x);
   mxDist = SquareRoot( Pw_2(x-tx) +  Pw_2(y-ty) ) / 2.;
   dist = -mxDist;
   a = -ORB_MAX_HEIGHT/Pw_2(mxDist);
   tz = DDTerrZ(x, y);
   o = ddeffect.createZ(ORB_MODEL_PATH, x, y, ORB_INITIAL_Z+tz,rad, ORB_SCALE);
   ot = ddeffect.createZ(TRAIL_MODEL_PATH, x, y, ORB_INITIAL_Z+tz, rad, TRAIL_SCALE);
   //o.Z = ORB_INITIAL_Z;
   spd = DD_INTERVAL * (2.*mxDist / ORB_TRAVEL_TIME);
   vx =  spd * Cos(rad);
   vy =  spd * Sin(rad);
   //tz = o.WZ;
   this.owner = owner;
   this.lvl = lvl;
   this.u = u;
   
   return this;
  }
  
  method LaunchOrb() {
   DDStartTim(DD_INTERVAL, true, this, function() {
    orb this = DDTimData();
    ddeffect oe;
    effect e;
    
    dist += spd;
    o.PositionZ(o.X + vx, o.Y + vy, a*Pw_2(dist) + ORB_MAX_HEIGHT+tz);
    ot.PositionZ(o.X, o.Y, o.Z);
    /*o.X += vx; o.Y += vy;
    o.Z = (tz-o.WZ) + a*Pw_2(dist) + ORB_MAX_HEIGHT;
    ot.X = o.X; ot.Y = o.Y; ot.Z = o.Z;*/
    
    if (dist > mxDist) {
     g = DDLoadGroup();
     DDGFilterDataSet(this);
     GroupEnumUnitsInRange(g, o.X, o.Y, FE_RADIUS[lvl], Filter(function() -> boolean {
      if (FE_UnitFilter(GetFilterUnit(), orb(DDGFilterData()).owner)) {
       orb(DDGFilterData()).cnt += 01;
       return true;
      }
      return false;
     }));
     
     if (cnt > 00) {
      dmg = FE_MAX_DAMAGE[lvl] / cnt; // division by zero?
      if (dmg > FE_DAMAGE[lvl])
       dmg = FE_DAMAGE[lvl];
     
      ForGroup(g, function() {
       orb o = DDGFilterData();
       unit e = GetEnumUnit();
       UnitDamageTarget(o.u, e, o.dmg, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null);
       if (!IsUnitType(e, UNIT_TYPE_FLYING) && !IsUnitType(e, UNIT_TYPE_DEAD) && FBEffect[H2ID(e)] == null) {
        FBEffect[H2ID(e)] = AddSpecialEffectTarget(FREEZE_EFFECT, e, "origin");
        PauseUnit(e, true);
       }
       e = null;
      });
      
      dmy = DDLoadSpellDummy(owner, o.X, o.Y, ABILITY_AIR_FREEZE, lvl);
      UnitRemoveAbility(dmy, 'Aloc');
      IssueTargetOrder(dmy, "frostnova", dmy);
      
      DDStartTim(FE_DURATION[lvl]-.05, false, this, function() {
       orb o = DDTimData();
       
       UnitAddAbility(o.dmy, 'Aloc');
       UnitRemoveAbility(o.dmy, ABILITY_AIR_FREEZE);
       DDRecycleDummy(o.dmy);
       
       ForGroup(o.g, function() {
        unit e = GetEnumUnit();
        if (!IsUnitType(e, UNIT_TYPE_FLYING) /*&& GetUnitAbilityLevel(e, BUFF_AIR_FREEZE) != 00*/) {
         PauseUnit(e, false);
         UnitRemoveAbility(e, BUFF_AIR_FREEZE);        
         DestroyEffect(FBEffect[H2ID(e)]);
         FBEffect[H2ID(e)] = null;
        }
        e = null;
       });
       DDRecycleGroup(o.g);
       o.destroy();
       DDQuitTim();
      });
     } else
      DDRecycleGroup(g);
     
     static if (USE_TERRAIN_TYPE_MODIFICATION)
      DDStartTim(TERRAIN_TEXTURE_DURATION, false, ModifieTerrainType(o.X, o.Y, FE_RADIUS[lvl]-bj_CELLWIDTH, p_null), function() {
       ModifieTerrainType(0., 0., 0., terrtype( DDTimData() ));
       DDQuitTim();
      });
     TerrainDeformCrater(o.X, o.Y, FE_RADIUS[lvl], EXPLOSION_DEAPTH, R2I(TERRAIN_DEFORMATION_DURATION*1000.), false);
     DDCameraSetSourceNoiseForPlayers(o.X, o.Y, CAMERA_MAGNITUDE, CAMERA_VELOCITY, SOUND_MAX_DISTANCE, CAMERA_NOISE_DURATION);
     oe = ddeffect.create(ORB_ERUPTION_EFFECT, o.X, o.Y, GetRandomReal(0., bj_PI*2.), ORB_ERUPTION_EFFECT_SIZE)/*.destroyx(2.)*/;
     oe.Animation(ANIM_TYPE_BIRTH);
     oe.AnimationSpeed(ORB_ERUPTION_EFFECT_ANIMATION_SPEED);
     oe.destroyx(2.*(ORB_ERUPTION_EFFECT_ANIMATION_SPEED/100.));
     //DestroyEffectTimed(AddSpecialEffect(ORB_ERUPTION_EFFECT, o.X, o.Y), 3.);
     e = AddSpecialEffect(ORB_EXPLOSION_EFFECT, o.X, o.Y);
     BlzSetSpecialEffectScale(e, ORB_EXPLOSION_EFFECT_SIZE);
     BlzSetSpecialEffectTimeScale(e, ORB_EXPLOSION_EFFECT_ANIMATION_SPEED/100.);
     DestroyEffect(e); e = null;
     if (GetRandomInt(00, 01) == 01)
      DDGenericSound(SPELL_EXPLODE_SOUND_1, SPELL_EXPLODE_SOUND_VOL, o.X, o.Y, SOUND_MAX_DISTANCE, 1.);
     else
      DDGenericSound(SPELL_EXPLODE_SOUND_2, SPELL_EXPLODE_SOUND_VOL, o.X, o.Y, SOUND_MAX_DISTANCE, 1.);
     
     //ot.X = DDMaxX; ot.Y = DDMaxY;
     o.destroy();
     ot.destroy();
     DDQuitTim();
    }
    
   });
  }
 }

 //====================================================================================
 // Main Setup Function For FE
 function onInit() {
  // Load locals...
  trigger tg = CreateTrigger();
  
  // Setup user spell
  SetupFrostEruption();
  
  // Register trigger events
  TriggerRegisterAnyUnitEventBJ(tg, EVENT_PLAYER_UNIT_SPELL_EFFECT);
  TriggerRegisterAnyUnitEventBJ(tg, EVENT_PLAYER_UNIT_DEATH);
  TriggerAddCondition(tg, Condition(function() -> boolean {
   unit u;
   real x, y,
     tx, ty;
   orb o;
   
   if (GetTriggerEventId() == EVENT_PLAYER_UNIT_DEATH) {
    u = GetTriggerUnit();
    if (FBEffect[H2ID(u)] != null) {
     PauseUnit(u, false);
     DestroyEffect(FBEffect[H2ID(u)]);
     FBEffect[H2ID(u)] = null;
    }
    u = null;
    return false;
   }
   
   if (GetSpellAbilityId() != ABILITY_FROST_ERUPTION)
    return false;
   
   u = GetTriggerUnit();
   x = GetWidgetX(u); y = GetWidgetY(u);
   tx = GetSpellTargetX(); ty = GetSpellTargetY();
   
   
   o = orb.create(u, x, y, tx, ty, GetOwningPlayer(u), GetUnitAbilityLevel(u, ABILITY_FROST_ERUPTION));
   DDGenericSound(SPELL_START_SOUND, SPELL_START_SOUND_VOL, SOUND_MAX_DISTANCE, x, y, 1.);
   o.LaunchOrb();
   
   u = null;
   return false;
  }));

 }

}
//! endzinc[/B]

[B]

Algid Aura

Slowes down units around caster for x seconds and dealing slight damage every x seconds (pulse width), while chilling lasts less time.


JASS:
[/B]
//TESH.scrollpos=24
//TESH.alwaysfold=0
//**************************************************************************************
//                              Installation:
//
//
// - 1. Made on Warcraft III v1.30
// - 2. Copy this trigger and DD Library to your map.
// - 3. Go to Import Manager (F12) and extract icons: BTNAlgirAura.blp and its: DISBTN, PAS and DISPAS version
// - 4. Import all of this to your map and set there path to as you can see here (in my map)
// - 5. Go to Object Manager (F6) and copy:
//  abilities: Algid Aura (Dummy) and main ability Algid Aura
//  buffs: Algid Aura (Buff) and Algid Aura (Ability Buff)
//  When you are pasting them to your map make sure you
//      type the following rawcodes or modify them below:
//      Algid Aura:         'Algd'
//      Algid Aura (Dummy):     'Aldm'
//      Algid Aura (Buff):   'Alga'
//      Algid Aura (Ability Buff): 'AlgB'
// - 6. Edit data below to your own will and enjoy the aura:
//
//**************************************************************************************

//! zinc
library AlgidAura requires DDLib
{

 // *****************************************************************************************
 //        === Main Data ===
 // *****************************************************************************************
 
    // Default: 'Algd'
    constant  integer    ABILITY_ALGID_AURA         = 'Algd';
    // Default: 'Aldm'
    constant  integer    ABILITY_ALGID_AURA_DUMMY       = 'Aldm';
 // Default: "frostnova"
    constant  string     ABILITY_ALGID_AURA_DUMMY_ORDER_ID     = "frostnova";
 
 
 real AA_PULSE_WIDTH[];
 
 // *****************************************************************************************
 
 // Edit this to match your level data
 function SetupAlgidAura() {
  // Spells damage:
  // Default: 5 / 5 / 4
  AA_PULSE_WIDTH[01]    = 5.;
  AA_PULSE_WIDTH[02]    = 5.;
  AA_PULSE_WIDTH[03]    = 4.;
 }
 
 // *****************************************************************************************
 
 timer  AATim[];
 
 struct data {
  unit u;
  unit d;
  
  static thistype  Data[];
 }

 //====================================================================================
 // Main Setup Function For FE
 function onInit() {
  // Load locals...
  trigger tg = CreateTrigger();
  
  // Setup user spell
  SetupAlgidAura();
  
  // Register trigger events
  TriggerRegisterAnyUnitEventBJ(tg, EVENT_PLAYER_HERO_SKILL);
  TriggerAddCondition(tg, Condition(function() -> boolean {
   unit u;
   integer id;
   data d;
   
   if (GetLearnedSkill() != ABILITY_ALGID_AURA)
    return false;
   
   u = GetTriggerUnit();
   id = H2ID(u);
   if (AATim[id] == null) {
    AATim[id] = CreateTimer();
    d = data.create();
    data.Data[H2ID(AATim[id])] = d;
    d.u = u; d.d = DDLoadDummy();
    UnitRemoveAbility(d.d, 'Aloc');
    SetUnitOwner(d.d, GetOwningPlayer(u), false);
    UnitAddAbility(d.d, ABILITY_ALGID_AURA_DUMMY);
   } else
    d = data.Data[H2ID(AATim[id])];
   SetUnitAbilityLevel(d.d, ABILITY_ALGID_AURA_DUMMY, GetLearnedSkillLevel());
   
   TimerStart(AATim[id], AA_PULSE_WIDTH[GetLearnedSkillLevel()], true, function() {
    data d = data.Data[H2ID(GetExpiredTimer())];
    
    if (!IsUnitType(d.u, UNIT_TYPE_DEAD)) {
     SetUnitX(d.d, GetWidgetX(d.u));
     SetUnitY(d.d, GetWidgetY(d.u));
     IssueTargetOrder(d.d, ABILITY_ALGID_AURA_DUMMY_ORDER_ID, d.d);
    }
   });
   
   u = null;
   return false;
  }));

 }

}
//! endzinc
[B]

Nature Blessing

Raises magic missiles from the ground, which travel at position of caster, exploding and protecting any ally unit with shield which reduces any taken damage, as well it increases n% hp regeneration per point of life missing.


JASS:
[/B]
//TESH.scrollpos=30
//TESH.alwaysfold=0
/*
 **********************************************************************************************************
 
          Installation:
  
  1) Copy this trigger and 'DD Library' to your map
  2) Copy Nature Blessing abilitie to your map
  3) Export and Import 'GaiaShield.mdx', 'GaiaMissile.mdx', 'NatureExplosion.mdx' sound from this map to yours
  4) Modify constants to your liking below
  5) Made on Warcraft III v1.30
 
 **********************************************************************************************************
*/

//! zinc
library NatureBlessing requires DDLib
{

  // This is the main raw code of ability Nature Blessing
  // Default: 'Nbls'
  constant integer   NATURE_BLESSING     = 'Nbls';
  
  // Natures shield effect model path
  // Default: "Spells\\NatureBlessing\\GaiaShield.mdx"
  constant string   NATURE_SHIELD_EFFECT   = "Spells\\NatureBlessing\\GaiaShield.mdx";
  
  // Natures missile effect model path
  // Default: "Spells\\NatureBlessing\\GaiaMissle.mdx"
  constant string   NATURE_MISSILE_EFFECT   = "Spells\\NatureBlessing\\GaiaMissle.mdx";
  
  // Natures explosion model effect path
  // Default: "Spells\\NatureBlessing\\NatureExplosion.mdx"
  constant string   NATURE_EXPLOSION_EFFECT   = "Spells\\NatureBlessing\\NatureExplosion.mdl";
  
  // Natures missile fire sound path (this sound is played when missiles start to move)
  // Default: "Abilities\\Spells\\NightElf\\Tranquility\\TranquilityTarget1.wav"
  constant string   NATURE_SHOOT_SOUND    = "Abilities\\Spells\\NightElf\\Tranquility\\TranquilityTarget1.wav";
  constant real   NATURE_SHOOT_SOUND_VOL   = 100.;
  constant real   NATURE_SHOOT_SOUND_PITCH  = 1.5;
  constant real   NATURE_SHOOT_SOUND_MAX_DISTANCE = 3500.;
  
  // Nature explosion sound file path (is played when nature explosion is caused)
  // Default: "Abilities\\Spells\\NightElf\\Tranquility\\Tranquility.wav"
  constant string   NATURE_EXPLOSION_SOUND   = "Abilities\\Spells\\NightElf\\Tranquility\\Tranquility.wav";
  constant real   NATURE_EXPLOSION_SOUND_VOL  = 90.;
  
  // This is number of nature missiles created
  // Default: 12
  constant integer   MISSILES_COUNT     = 12;
  // Default: 1.2
  constant real   MISSILE_SIZE     = 1.2;
  
  // This is min and max distance from caster to missiles start point
  // Default: 400 / 600
  constant real   MISSILE_MIN_DISTANCE   = 400.;
  constant real   MISSILE_MAX_DISTANCE   = 600.;
  
  // This is min and max finish height / caster position of missiles
  // Default: 75 / 400
  constant real   MISSILE_MIN_HEIGHT    = 40.;
  constant real   MISSILE_MAX_HEIGHT    = 400.;
  
  // This is missiles value which tells how much time they need to reach caster and how long it takse for them to manifest
  // Default: 0.75 / 0.5
  constant real   MISSILE_TRAVEL_TIME    = .9;
  constant real   MISSILE_BIRTH_TIME    = 0.5;
  
  // Default: 50
  constant real   MISSILE_INITIAL_HEIGHT   = 10.;
  
  // Default: 0.2 seconds
  constant real   HEAL_INTERVAL     = .2;
  // --------------------------------------------------------------
  // *** Do not edit level variables here edit them below ***
  real   EXPLOSION_AOE[];
  real   SHIELD_PROTECT[];
  real   HEAL_PERC_AMOUNT[];
  real   SPELL_DURATION[];
 
 // -----------------------------------------------------------------
 //     *** Edit level data here ***
 function NatureBlessingLevelSetup() {
  // This is AOE of explosion "effect"
  // Default: 410 / 530 / 650
  EXPLOSION_AOE[01] = 410.;
  EXPLOSION_AOE[02] = 530.;
  EXPLOSION_AOE[03] = 650.;
  
  // Shield protection is amount of damage reduced in percentage
  // Default: 15 / 25 / 35
  SHIELD_PROTECT[01] = 15.;
  SHIELD_PROTECT[02] = 25.;
  SHIELD_PROTECT[03] = 35.;
  
  // This is heal amount in percentage per point of life missing
  // Default: 5 / 7 / 9
  HEAL_PERC_AMOUNT[01] = 5.;
  HEAL_PERC_AMOUNT[02] = 7.;
  HEAL_PERC_AMOUNT[03] = 9.;
  
  // This is how long spell lasts in seconds
  // Default: 10 / 10 / 10
  SPELL_DURATION[01] = 10.;
  SPELL_DURATION[02] = 10.;
  SPELL_DURATION[03] = 10.;
 }
 
 function PickUnitsFilter(unit f, player owner) -> boolean {
  return IsUnitAlly(f, owner)         &&
      !IsUnitType(f, UNIT_TYPE_DEAD)       &&
      !IsUnitType(f, UNIT_TYPE_STRUCTURE)      &&
      !BlzIsUnitInvulnerable(f)       &&
      !DDIsUnitWard(f)          &&
      !IsUnitType(f, UNIT_TYPE_MAGIC_IMMUNE)    &&
      !IsUnitType(f, UNIT_TYPE_MECHANICAL);
 }
 
 // #####################################################################################
 // #####################################################################################
 
 timer   Tim = null;
 group   Grp = null;
 
 struct unitdata {
  real dur, heal, shield;
  effect e;
  
  static thistype Att[];
 }
 
 struct missiles {
  ddeffect m[MISSILES_COUNT];
  p_real   pos[MISSILES_COUNT];
  p_real  spd[MISSILES_COUNT];
  integer  cnt;
  
  real  X, Y;
  player  owner;
  integer  lvl;
  
  
  static method create(unit c) -> thistype {
   thistype this = allocate();
   integer i;
   real x = GetWidgetX(c), y = GetWidgetY(c);
   real rad = 0., d;
   
   X = x; Y = y;
   owner = GetOwningPlayer(c);
   lvl = GetUnitAbilityLevel(c, NATURE_BLESSING);
   
   cnt = R2I((MISSILE_TRAVEL_TIME-.1) / DD_INTERVAL);
   for(i=00; i < MISSILES_COUNT; i+=01) {
    rad += bj_PI/6.;
    d = GetRandomReal(MISSILE_MIN_DISTANCE, MISSILE_MAX_DISTANCE);
    pos[i] = pVector(x + d * Cos(rad), y + d * Sin(rad), MISSILE_INITIAL_HEIGHT);
    spd[i] = pVector(-Cos(rad) * DD_INTERVAL * d / MISSILE_TRAVEL_TIME,
         -Sin(rad) * DD_INTERVAL * d / MISSILE_TRAVEL_TIME,
         DD_INTERVAL * (GetRandomReal(MISSILE_MIN_HEIGHT, MISSILE_MAX_HEIGHT)-MISSILE_INITIAL_HEIGHT) / MISSILE_TRAVEL_TIME);
    m[i] = ddeffect.createZ(NATURE_MISSILE_EFFECT, pos[i][00], pos[i][01], pos[i][02] + DDTerrZ(pos[i][00], pos[i][01]), rad, MISSILE_SIZE);
   }
   
   return this;
  }
  
  method destroy() {
   integer i;
   
   for(i=00; i < MISSILES_COUNT; i+=01) {
    m[i].destroy();
    pos[i].destroy();
    spd[i].destroy();
   }
   deallocate();
  }
  
  method Step() -> boolean {
   integer i;
   
   for(i=00; i < MISSILES_COUNT; i+=01) {
    pos[i][00] += spd[i][00];
    pos[i][01] += spd[i][01];
    pos[i][02] += spd[i][02];
    
    m[i].PositionZ(pos[i][00], pos[i][01], pos[i][02]);
    //m[i].Y = pos[i][01];
    //m[i].Z = pos[i][02];
   }
   
   cnt -= 01;
   return (cnt == 00);
  }
  
 }
 
 
 // ==========================================================================================
 function onInit() {
  trigger t = CreateTrigger();
  
  Grp = CreateGroup();
  NatureBlessingLevelSetup();
  
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT);
  TriggerAddCondition(t, Condition(function() -> boolean {
   missiles ms;
   unit u;
   
   if (GetSpellAbilityId() != NATURE_BLESSING)
    return false;
   
   u = GetTriggerUnit();
   ms = missiles.create(u);
   
   // Play sound and shake camera for players within spell cast range
   DDGenericSound(NATURE_SHOOT_SOUND, NATURE_SHOOT_SOUND_VOL, GetWidgetX(u), GetWidgetY(u), NATURE_SHOOT_SOUND_MAX_DISTANCE, NATURE_SHOOT_SOUND_PITCH);
   
   DDStartTim(MISSILE_BIRTH_TIME, false, ms, function() {
    DDStartTim(DD_INTERVAL, true, DDTimData(), function() {
     missiles ms = DDTimData();
     trigger t;
     
     if (ms.Step()) {
      DDGenericSound(NATURE_EXPLOSION_SOUND, NATURE_EXPLOSION_SOUND_VOL, ms.X, ms.Y, NATURE_SHOOT_SOUND_MAX_DISTANCE, 1.8);
      ddeffect.create(NATURE_EXPLOSION_EFFECT, ms.X, ms.Y, GetRandomReal(0., bj_PI*2.), EXPLOSION_AOE[ms.lvl]/250.).destroyx(3.);
      
      DDGroupFilterArea(ms.X, ms.Y, EXPLOSION_AOE[ms.lvl], ms, function() -> boolean {
       unitdata ud;
       missiles ms = DDGFilterData();
       unit f = GetFilterUnit();
       
       if (PickUnitsFilter(f, ms.owner)) {
        if (ud.Att[GetHandleId(f)-0x100000] == p_null) {
         ud = unitdata.create();
         ud.Att[GetHandleId(f)-0x100000] = ud;
         ud.e = AddSpecialEffectTarget(NATURE_SHIELD_EFFECT, f, "origin");
         GroupAddUnit(Grp, f);
        } else
         ud = ud.Att[GetHandleId(f)-0x100000];
        
        ud.heal   = HEAL_PERC_AMOUNT[ms.lvl] / 100.;
        ud.shield   = SHIELD_PROTECT[ms.lvl] / 100.;
        ud.dur    = SPELL_DURATION[ms.lvl];
       }
       
       f = null;
       return false;
      });
      
      if (Tim == null) {
       Tim = DDLoadTim();
      
      TimerStart(Tim, HEAL_INTERVAL, true, function() {
       ForGroup(Grp, function() {
        unit e = GetEnumUnit();
        unitdata ud = unitdata.Att[GetHandleId(e)-0x100000];
        
        SetWidgetLife( e, GetWidgetLife(e) + (HEAL_INTERVAL * ud.heal * (GetUnitState(e, UNIT_STATE_MAX_LIFE)-GetWidgetLife(e))) );
        
        ud.dur -= .2;
        if (ud.dur < 0. || IsUnitType(e, UNIT_TYPE_DEAD)) {
         GroupRemoveUnit(Grp, e);
         ud.Att[GetHandleId(e)-0x100000] = p_null;
         DestroyEffect(ud.e);
         ud.e = null;
         ud.destroy();
         if (FirstOfGroup(Grp) == null) {
          DDRecycleTim(Tim);
          Tim = null;
         }
        }
        
        e = null;
       });
      });
      
      }
      
      ms.destroy();
      DDQuitTim();
     }
    });
    DDQuitTim();
   });
   
   u = null;
   return false;
  }));
  
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  t = CreateTrigger();
  DDTriggerRegisterAnyUnitDamaged(t);
  TriggerAddCondition(t, Condition(function() -> boolean {
   unit u = GetTriggerUnit();
   unitdata ud = unitdata.Att[GetHandleId(u)-0x100000];
    
   if (ud == p_null) {
    u = null;
    return false;
   }
   
   SetWidgetLife(u, GetWidgetLife(u) + (GetEventDamage() * ud.shield));
   
   u = null;
   return false;
  }));
  
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
 }
 
}
//! endzin
[B]

Instinct Flash

Quickly moves to targeted point dealing heavy damage to any enemy unit which comes near caster.


JASS:
[/B]
//TESH.scrollpos=15
//TESH.alwaysfold=0
//**************************************************************************************
//                              Installation:
//
//
// - 1. Made on Warcraft III v1.30
// - 2. Copy 'this trigger' and 'DD Library' to your map.
// - 3. Go to Import Manager (F12) and extract icons: BTNInstinctFlash.blp and DISBTN versions
//      sounds: sword_chop.wav, sword_echo.wav, sword_draw.wav, sword_dmg1.wav, sword_dmg2.wav
// - 4. Import all of this to your map and set there path to as you can see here (in my map)
// - 5. Go to Object Manager (F6) and copy:
//  units: Illusion Blademaster
//  ability: Instinct Flash
//  When you are pasting them to your map make sure you type the following rawcodes:
//      Illusion Blademaster:   'ssib'
//  Instinct Flash:         'InFl'
// - 6. If you want different raw codes you must edit them below as well:
// - 7. Edit data below to your own will and enjoy!
//
//**************************************************************************************

//! zinc
library InstinctFlash requires DDLib
{

  // *****************************************************************************************
  //        === Main Data ===
  // *****************************************************************************************
    
  // This is the raw code of the spell
  // Default: InFl
  constant integer   ABILITY_INSTINCT_FLASH     = 'InFl';
  
  // This is the raw code of illusion
  // Default: ssib
  constant integer   UNIT_ILLUSION_RAWCODE     = 'ssib';
  
  // *****************************************************************************************
  //        === Effects ===
  // *****************************************************************************************
  
  // Model file of spells motion sfx
  // Default: Abilities\\Weapons\\ZigguratMissile\\ZigguratMissile.mdl
  constant string   EFFECT_BLADE_ATTACHMENT     = "Abilities\\Weapons\\ZigguratMissile\\ZigguratMissile.mdl";
  constant string   EFFECT_BLADE_ATTACH_POINT    = "weapon";
  // Default: Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl
  constant string   EFFECT_WATER_IMPACT      = "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl";
  // Default: Objects\\SpawnQModels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl
  constant string   EFFECT_GROUND_IMPACT     = "Objects\\SpawnModels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl";
  // Default: Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl
  constant string   EFFECT_UNIT_SLASH_BLEAD     = "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl";
  
  
  // *****************************************************************************************
  //        === Sounds ===
  // *****************************************************************************************
  
  // Default: Custom\\Spells\\Instinct Flash\\sword_draw.wav
  constant string   SOUND_DRAW        = "Custom\\Spells\\Instinct Flash\\sword_draw.wav";
  // Default: 85.
  constant real   SOUND_DRAW_VOL       = 85.;
  // Default: Custom\\Spells\\Instinct Flash\\sword_echo.wav
  constant string    SOUND_ECHO        = "Custom\\Spells\\Instinct Flash\\sword_echo.wav";
  // Default: 45.
  constant real   SOUND_ECHO_VOL       = 45.;
  // Default: Custom\\Spells\\Instinct Flash\\sword_dmg1.wav
  constant string   SOUND_DMG1        = "Custom\\Spells\\Instinct Flash\\sword_dmg1.wav";
  // Default: 45.
  constant real   SOUND_DMG1_VOL       = 85.;
  // Default: Custom\\Spells\\Instinct Flash\\sword_dmg2.wav
  constant string   SOUND_DMG2        = "Custom\\Spells\\Instinct Flash\\sword_dmg2.wav";
  // Default: 85.
  constant real   SOUND_DMG2_VOL       = 85.;
  // Default: Custom\\Spells\\Instinct Flash\\sword_chop.wav
  constant string   SOUND_CHOP        = "Custom\\Spells\\Instinct Flash\\sword_chop.wav";
  // Default: 85.
  constant real   SOUND_CHOP_VOL       = 85.;
  // Default: 3500.
  constant real   SOUND_MAX_DISTANCE      = 3500.;
  
  // *****************************************************************************************
  //        === Initial Illusions ===
  // *****************************************************************************************
  
        // Max illusion creation distance (height)
  // Default: 300
  constant real   ILLUSION_HEIGHT       = 300.;
  
  // Max illusion creation distance (width)
  // Default: 550
  constant real   ILLUSION_WIDTH       = 550.;
  
  // This is duration of illusions in seconds
  // Default: 0.6
  constant real   ILLUSION_DURATION      = .6;
  
  // This is the animation speed of illusions in percentage
  // Default: 100*(1.4-0.15)*0.4 ( 1.4 = Animation duration, 0.4 = Illusion duration, -0.15 extra constant value )
  constant real   ILLUSION_ANIMATION_SPEED    = 70.;
  
  // This is animation of illusion which should be played
  // Default: 9 (stand ready)
  constant integer   ILLUSION_ANIMATION_ID     = 9; // (1.4)
  
  // Maximum number of illusions at same time
  // Default: 8
  constant integer   MAX_ILLUSIONS       = 8;
  constant integer   MAX_ILLUSIONS_ARRAY      = 4;
  
  // 
  constant integer   ILLUSION_COLOR_RED      = 125;
  constant integer   ILLUSION_COLOR_GREEN     = 125;
  constant integer   ILLUSION_COLOR_BLUE      = 240;
  constant integer   ILLUSION_COLOR_ALPHA     = 128;
  
  // *****************************************************************************************
  //        === Caster Motion ===
  // *****************************************************************************************
  
  // This is casters end animation
  // Default: 8 (attack 2)
  constant integer   CASTER_ATTACK_ANIMATION_ID    = 8; // (1.134)
  // Speed at which caster is traveling after multiple illusions are fused
  // Default: 1000.
  constant real   CASTER_SPEED       = 1000.;
  // Default: 150
  constant integer   CASTER_COLOR_ALPHA      = 150;
  // Casters end animation speed in percentage
  // Default: 200
  constant real   CASTER_ANIMATION_SPEED     = 200.;
  // This is the area of damage effect
  // Default: 135
  constant real   CASTER_DAMAGE_RANGE      = 135.;
  
  // *****************************************************************************************
  //        === Killed Units Motion  ===
  // *****************************************************************************************
  
  // Defines travel distance of units which are pushed
  // Default: 330
  constant real   PUSH_DISTANCE       = 330.;
  
  // Defines travel height of units which are pushed
  // Default: 230
  constant real   PUSH_HEIGHT        = 230.;
  
  // Defines start push speed
  // Default: 500
  constant real   PUSH_SPEED        = 500.;
  
  // *****************************************************************************************
  //   *** (Aftereffect Illusions From Casters Movement) ***
  // *****************************************************************************************
  
  // This is casters end animation
  // Default: 8 (attack 2)
  constant integer   AEFF_ILLUSION_ATTACK_ANIMATION_ID  = 8; // (1.134)
  
  // Duration of casters end animation
  // Default: 0.66
  constant real   AEFF_ILLUSION_DURATION     = .66;
  
  // Casters end animation speed in percentage
  // Default: 100*1.134/0.5 (1.134 = animation duration, 0.5 seconds to finish animation)
  constant real   AEFF_ILLUSION_ANIMATION_SPEED   = 226.8;
  
  // How much distance caster passes to produce a single aftereffect illusion
  // Default: 125.
  constant real   AEFF_ILLUSION_DISTANCE_STEP    = 125.;
  
  
  real   DamageAmount[];
 
 // *****************************************************************************************
 //        === Level Data ===
 // *****************************************************************************************
 
 // *** Edit level data below ***
 function InstinctFlash_Setup() {
  // *** This is the damage per level ***
  // Default: 175 / 285 / 400
  DamageAmount[01]  = 175.;
  DamageAmount[02]  = 285.;
  DamageAmount[03]  = 400.;
  
  // *** This is the color of illusions ***
  // Arguments: red, green, blue, alpha (from 0 to 255)
  // Default: 125, 125, 240, 255
  //Color = CreateColor(125, 125, 240, 255)
  
 }
 
 // *****************************************************************************************
 //        === Unit Filter ===
 // *****************************************************************************************
 
 function UnitFilter_Setup(unit u, player p) -> boolean {
  return !IsUnitType(u, UNIT_TYPE_STRUCTURE)    &&
      !IsUnitType(u, UNIT_TYPE_FLYING)     &&
      !IsUnitType(u, UNIT_TYPE_MECHANICAL)    &&
      !BlzIsUnitInvulnerable(u)      &&
      !DDIsUnitWard(u)         &&
      !IsUnitType(u, UNIT_TYPE_DEAD)     &&
      IsUnitEnemy(u, p);
      
 }
 
 
 // ==============================================================================
 //     DO NOT EDIT BELOW IF YOU DONT KNOW JASS
 // ==============================================================================
 
 struct uknockback {
  unit u;
  real x, y, wz;
  real dx, dy;
  real a, dist;
  
  static method create(unit u, real rad) -> thistype {
   thistype this = allocate();
   
   this.u = u;
   UnitAddAbility(u, DD_ABILITY_CROWN_FORM);
   x = GetWidgetX(u); y = GetWidgetY(u); wz = DDTerrZ(x, y);
   a = PUSH_HEIGHT / Pw_2(PUSH_DISTANCE/2.);
   dx = DD_INTERVAL * PUSH_SPEED * Cos(rad);
   dy = DD_INTERVAL * PUSH_SPEED * Sin(rad);
   dist = PUSH_DISTANCE;
   
   return this;
  }
  
  method ApplyMotion() {
   DDStartTim(DD_INTERVAL, true, this, function() {
    thistype this = DDTimData();
    
    x += dx; y += dy;
    SetUnitX(u, x); SetUnitY(u, y);
    SetUnitFlyHeight(u, wz - DDTerrZ(x, y) + PUSH_HEIGHT - a*Pw_2(dist-(PUSH_DISTANCE/2.)), 0.);
    
    dist -= DD_INTERVAL * PUSH_SPEED;
    if (dist < 0.) {
     if (!IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY/*AMPHIBIOUSPATHING*/))
      DestroyEffect(AddSpecialEffect(EFFECT_WATER_IMPACT, x, y));
     else
      DestroyEffect(AddSpecialEffect(EFFECT_GROUND_IMPACT, x, y));
     u = null;
     destroy();
     DDQuitTim();
    }
   });
  }
 }
 
 struct iflash {
  unit u;
  player p;
  effect e;
  real x, y;
  real dx, dy;
  real dist, spd;
  group g, gd;
  integer lvl;
  real fac;
  
  static method create(unit u, real tx, real ty, real rad) -> thistype {
   thistype this = allocate();
   
   this.u = u;
   fac = bj_RADTODEG*rad;
   lvl = GetUnitAbilityLevel(u, ABILITY_INSTINCT_FLASH);
   p = GetOwningPlayer(u);
   x = GetUnitX(u); y = GetUnitY(u);
   spd = DD_INTERVAL * CASTER_SPEED;
   dx = spd * Cos(rad); dy = spd * Sin(rad);
   dist = SquareRoot( DDHypot(tx-x, ty-y) );
   g = DDLoadGroup(); gd = DDLoadGroup();
   
   SetUnitPathing(u, false);
   SetUnitAnimationByIndex(u, CASTER_ATTACK_ANIMATION_ID);
   ShowUnit(this.u, true);
   PauseUnit(u, true);
   e = AddSpecialEffectTarget(EFFECT_BLADE_ATTACHMENT, this.u, EFFECT_BLADE_ATTACH_POINT);
   SetUnitVertexColor(u, 255, 255, 255, CASTER_COLOR_ALPHA);
   SetUnitTimeScale(u, CASTER_ANIMATION_SPEED/100.);
   
   return this;
  }
  
  method ApplyMotion() {
   DDStartTim(DD_INTERVAL, true, this, function() {
    thistype this = DDTimData();
    unit ae_ill;
    
    x += dx; y += dy;
    dist -= spd;
    SetUnitX(u, x); SetUnitY(u, y);
    
    if (ModuloReal(dist, AEFF_ILLUSION_DISTANCE_STEP) < spd) {
     ae_ill = CreateUnit(Player(15), UNIT_ILLUSION_RAWCODE, x, y, fac);
     SetUnitColor(ae_ill, GetPlayerColor(p));
     SetUnitVertexColor(ae_ill, ILLUSION_COLOR_RED, ILLUSION_COLOR_GREEN, ILLUSION_COLOR_BLUE, CASTER_COLOR_ALPHA);
     SetUnitPathing(ae_ill, false);
     SetUnitX(ae_ill, x); SetUnitY(ae_ill, y);
     PauseUnit(ae_ill, true);
     SetUnitAnimationByIndex(ae_ill, CASTER_ATTACK_ANIMATION_ID);
     DestroyEffect(AddSpecialEffectTarget(EFFECT_BLADE_ATTACHMENT, ae_ill, EFFECT_BLADE_ATTACH_POINT));
     DDFadeUnit(ae_ill, CASTER_COLOR_ALPHA, 00, AEFF_ILLUSION_DURATION);
    }
    
    DDGFilterDataSet(this);
    GroupEnumUnitsInRange(g, x, y, CASTER_DAMAGE_RANGE, Filter(function() -> boolean {
     thistype this = DDGFilterData();
     unit f = GetFilterUnit();
     if (UnitFilter_Setup(f, p) && !IsUnitInGroup(f, gd)) {
      //UnitDamageTarget(u, f, DamageAmount[lvl], true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null);
      DDSpellDamage(u, f, DamageAmount[lvl]);
      DestroyEffect(AddSpecialEffectTarget(EFFECT_UNIT_SLASH_BLEAD, f, "origin"));
      GroupAddUnit(gd, f);
      if (GetRandomInt(00, 01) == 01)
       DDGenericSound(SOUND_DMG1, SOUND_DMG1_VOL, x, y, SOUND_MAX_DISTANCE, 1.);
      else
       DDGenericSound(SOUND_DMG2, SOUND_DMG2_VOL, x, y, SOUND_MAX_DISTANCE, 1.);
      
      if (IsUnitType(f, UNIT_TYPE_DEAD)) {
       uknockback.create(f, Atan2(GetWidgetY(f)-GetWidgetY(u), GetWidgetX(f)-GetWidgetX(u))).ApplyMotion();
       DDGenericSound(SOUND_CHOP, SOUND_CHOP_VOL, x, y, SOUND_MAX_DISTANCE, 1.);
      }
     }
     
     f = null;
     return false;
    }));
    
    if (dist < 0.) {
     SetUnitPathing(u, true);
     PauseUnit(u, false);
     SetUnitTimeScale(u, 1.);
     SetUnitVertexColor(u, 255, 255, 255, 255);
     DDStartTim(.6, false, New_pUnit(u), function() {
      p_unit pu = DDTimData();
      SetUnitAnimation(pu[00], "stand");
      pu.destroy();
      DDQuitTim();
     });
     if (GetLocalPlayer() == p)
      SelectUnit(u, true);
     DDRecycleGroup(g);
     DDRecycleGroup(gd);
     DestroyEffect(e);
     e = null;
     destroy();
     DDQuitTim();
    }
   });
  }
 }
 

 struct illusions {
  unit il[MAX_ILLUSIONS], u;
  real dist[MAX_ILLUSIONS_ARRAY];
  effect e[MAX_ILLUSIONS];
  real w_spd;
  real dx, dy;
  real dx2, dy2;
  real x, y, tx, ty;
  real rad;
  
  static method create(unit u, real tx, real ty) -> thistype {
   thistype this = allocate();
   integer i;
   playercolor pc = GetPlayerColor(GetOwningPlayer(u));
   real px, py;
   
   this.u = u;
   this.tx = tx; this.ty = ty;
   x = GetUnitX(u); y = GetUnitY(u);
   w_spd = DD_INTERVAL * ILLUSION_HEIGHT / ILLUSION_DURATION;
   rad = Atan2(ty-y, tx-x);
   dx = Cos(rad); dy = Sin(rad);
   
   for(i=01; i < MAX_ILLUSIONS_ARRAY+01; i+=01) {
    px = x + (i*ILLUSION_WIDTH)/MAX_ILLUSIONS * -dy;
    py = y + (i*ILLUSION_WIDTH)/MAX_ILLUSIONS * dx;
    px += ( (ILLUSION_HEIGHT / Pw_2(ILLUSION_WIDTH/02)) ) * Pw_2((i-01)*ILLUSION_WIDTH/MAX_ILLUSIONS) * dx;
    py += ( (ILLUSION_HEIGHT / Pw_2(ILLUSION_WIDTH/02)) ) * Pw_2((i-01)*ILLUSION_WIDTH/MAX_ILLUSIONS) * dy;
    il[i-01] = CreateUnit(Player(15), UNIT_ILLUSION_RAWCODE, px, py, bj_RADTODEG*rad);
    e[i-01] = AddSpecialEffectTarget(EFFECT_BLADE_ATTACHMENT, il[i-01], "weapon");
    SetUnitVertexColor(il[i-01], ILLUSION_COLOR_RED, ILLUSION_COLOR_GREEN, ILLUSION_COLOR_BLUE, ILLUSION_COLOR_ALPHA);
    SetUnitColor(il[i-01], pc);
    SetUnitTimeScale(il[i-01], ILLUSION_ANIMATION_SPEED/100.);
    SetUnitAnimationByIndex(il[i-01], ILLUSION_ANIMATION_ID);
    
    px = x - (i*ILLUSION_WIDTH)/MAX_ILLUSIONS * -dy;
    py = y - (i*ILLUSION_WIDTH)/MAX_ILLUSIONS * dx;
    px += ( (ILLUSION_HEIGHT / Pw_2(ILLUSION_WIDTH/02)) ) * Pw_2((i-01)*ILLUSION_WIDTH/MAX_ILLUSIONS) * dx;
    py += ( (ILLUSION_HEIGHT / Pw_2(ILLUSION_WIDTH/02)) ) * Pw_2((i-01)*ILLUSION_WIDTH/MAX_ILLUSIONS) * dy;
    il[(i-01)+MAX_ILLUSIONS_ARRAY] = CreateUnit(Player(15), UNIT_ILLUSION_RAWCODE, px, py, bj_RADTODEG*rad);
    e[i-01+MAX_ILLUSIONS_ARRAY] = AddSpecialEffectTarget(EFFECT_BLADE_ATTACHMENT, il[i-01+MAX_ILLUSIONS_ARRAY], "weapon");
    SetUnitVertexColor(il[(i-01)+MAX_ILLUSIONS_ARRAY], ILLUSION_COLOR_RED, ILLUSION_COLOR_GREEN, ILLUSION_COLOR_BLUE, ILLUSION_COLOR_ALPHA);
    SetUnitColor(il[(i-01)+MAX_ILLUSIONS_ARRAY], pc);
    SetUnitTimeScale(il[(i-01)+MAX_ILLUSIONS_ARRAY], ILLUSION_ANIMATION_SPEED/100.);
    SetUnitAnimationByIndex(il[(i-01)+MAX_ILLUSIONS_ARRAY], ILLUSION_ANIMATION_ID);
    
    dist[i-01] = (i*ILLUSION_HEIGHT*2.)/MAX_ILLUSIONS;
   }
   
   return this;
  }
  
  method ApplyMotion() {
   DDStartTim(DD_INTERVAL, true, this, function() {
    thistype this = DDTimData();
    integer i;
    real px, py;
    real sq;
    
    for(i=01; i < MAX_ILLUSIONS_ARRAY+01; i+=01) {
     dist[i-01] -=  w_spd;
     sq = SquareRoot(Pw_2(ILLUSION_WIDTH/02)*dist[i-01] / ILLUSION_HEIGHT);
     px = x + dist[i-01] * dx;
     py = y + dist[i-01] * dy;
     px += sq * -dy; // +90 degrees
     py += sq * dx;
     SetUnitX(il[i-01], px); SetUnitY(il[i-01], py);
     px = x + dist[i-01] * dx; 
     py = y + dist[i-01] * dy;
     px -= sq * -dy; // -90 degrees
     py -= sq * dx;
     SetUnitX(il[i-01+MAX_ILLUSIONS_ARRAY], px); SetUnitY(il[i-01+MAX_ILLUSIONS_ARRAY], py);
     
     if (dist[i-01] < 0. && il[i-01] != null) {
      RemoveUnit(il[i-01]);
      RemoveUnit(il[i-01+MAX_ILLUSIONS_ARRAY]);
      il[i-01] = null;
      il[i-01+MAX_ILLUSIONS_ARRAY] = null;
     }
    }
    
    if (il[MAX_ILLUSIONS_ARRAY-01] == null) {
     DDGenericSound(SOUND_ECHO, SOUND_ECHO_VOL, x, y, SOUND_MAX_DISTANCE, 1.);
     iflash.create(u, tx, ty, rad).ApplyMotion();
     destroy();
     DDQuitTim();
    }
   });
  }
 }
 
 // *** Main map startup function ***
 function onInit() {
  // *** Load locals ***
  trigger t = CreateTrigger();
  
  // *** Define users setup ***
  InstinctFlash_Setup();
  
  // *** Event / cond / act registering ***
  TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT);
  TriggerAddCondition(t, Condition(function() -> boolean {
   illusions il;
   unit u;
   
   if (GetSpellAbilityId() != ABILITY_INSTINCT_FLASH)
    return false;
   
   u = GetTriggerUnit();
   il = illusions.create(u, GetSpellTargetX(), GetSpellTargetY());
   il.ApplyMotion();
   ShowUnit(u, false);
   //SetUnitTimeScale(u, ILLUSION_ANIMATION_SPEED/100.);
   //SetUnitAnimationByIndex(u, ILLUSION_ANIMATION_ID);
   
   
   DDGenericSound(SOUND_DRAW, SOUND_DRAW_VOL, GetSpellTargetX(), GetSpellTargetY(), SOUND_MAX_DISTANCE, 1.);
   
   return false;
  }));
  
 }
 
}
//! endzinc


[B]

Summon Skeletons

Summons n skeletons which last for 50 seconds.



JASS:
//TESH.scrollpos=15
//TESH.alwaysfold=0
//**************************************************************************************
//                              Installation:
//
// - 1. Made on Warcraft III v1.30
// - 2. Go to Import Manager (F12) and extract NecroticBlast.mdx, BTNSummonSkeletons.blp (Credits: PrinceYaser) and its DISBTN version
// - 3. Import all of this to your map and set ther path to as you can see here (in my map)
// - 4. Go to Object Manager (F6) and copy "Summon Skeletons" ability.
//   When you are pasting them to your map make sure you match there rawcodes with ones below
// - 5. If you want different raw codes edit the below as well
// - 6. Edit data below to your own will and enjoy the spell
// - 7. Copy this trigger and "DD Library" to your map
//
//
//**************************************************************************************

//! zinc
library SummonSkeletons requires DDLib
{

 // *****************************************************************************************
 //        === Main Data ===
 // *****************************************************************************************
 
    // This is the raw code of the spell 'Summon Skeletons'
    // Default: 'A000'
    constant integer      ABILITY_SUMMON_SKELETONS       = 'A000';
 //constant real       SUMMON_SKELETONS_BLIGHT_DURATION    = 5.;
    constant real       SUMMON_SKELETONS_INTERVAL       = .33; // How offten are skeletons created
    constant real       SUMMON_SKELETONS_RISE_TIME       = 2.33;
    constant string       SUMMON_SKELETONS_RISE_ANIMATION     = "birth";
    constant real       SUMMON_SKELETONS_START_TRANSPARENCY    = 85.;
    constant real       SKELETONS_MIN_RISE_DISTANCE      = 125.; // Min distance from skeleton and caster
    constant real       SKELETONS_MIN_SPAWN_RANGE      = 100.; // Min distance between skeletons
    
 
 // *****************************************************************************************
 //        === Effect ===
 // *****************************************************************************************
 
 constant string      SUMMON_SKELETON_CASTER_EFFECT     = "Spells\\SummonSkeletons\\NecroticBlast.mdx"; // UgoUgo
 
 constant string      SUMMON_SKELETON_RISE_EFFECT      = "Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl";
 constant string      SUMMON_SKELETON_RISE_EFFECT_EX     = "Abilities\\Spells\\Undead\\RaiseSkeletonWarrior\\RaiseSkeleton.mdl";
 constant string      SUMMON_SKELETON_GROUND_EFFECT     = "Abilities\\Spells\\Undead\\PlagueCloud\\PlagueCloudCaster.mdl";//"SharedModels\\Smoke1_Green.mdl";
 constant real      SUMMON_SKELETON_GROUND_EFFECT_SIZE    = 1.;
 constant real      SUMMON_SKELETON_GROUND_EFFECT_HEIGHT   = -10.;
 
 constant string       SUMMON_SKELETONS_RISE_GRAVE_EFFECT    = "Abilities\\Spells\\Undead\\Graveyard\\GraveMarker.mdl";
 constant real       SUMMON_SKELETONS_RISE_GRAVE_EFFECT_FACING_OFFSET= 30.;
 constant real       SUMMON_SKELETONS_RISE_GRAVE_DURATION   = 6.;
 constant real       SUMMON_SKELETONS_RISE_GRAVE_DISTANCE_OFFSET  = 70.;
 
 constant string       SUMMON_SKELETONS_FIRE_EFFECT     = "Abilities\\Spells\\NightElf\\Immolation\\ImmolationDamage.mdl";
 constant string       SUMMON_SKELETONS_FIRE_EFFECT_ATTACH_1   = "foot left";
 constant string       SUMMON_SKELETONS_FIRE_EFFECT_ATTACH_2   = "foot right";
 constant string       SUMMON_SKELETONS_FIRE_EFFECT_ATTACH_3   = "hand left";
 constant string       SUMMON_SKELETONS_FIRE_EFFECT_ATTACH_4   = "hand right";
 constant string       SUMMON_SKELETONS_FIRE_EFFECT_ATTACH_5   = "head";
 constant string       SUMMON_SKELETONS_FIRE_EFFECT_ATTACH_6   = "origin";
 
 
    
 // *****************************************************************************************
 //        === Level Data ===
 // *****************************************************************************************
 
 // --------------------------------------------------------------
    // This variables are not supposed to be modified here, modify them below in Setup function
 integer    SKELETONS_TYPE_COLOR_RED[];
 integer    SKELETONS_TYPE_COLOR_GREEN[];
 integer    SKELETONS_TYPE_COLOR_BLUE[];
    integer    SKELETONS_COUNT[];
    integer    SKELETONS_TYPE_ID[];
 real    SKELETONS_LIFESPAN[];
    real     SKELETONS_MAX_RISE_DISTANCE[];
    real     SUMMON_SKELETONS_RISE_GRAVE_SIZE[];
    
 // --------------------------------------------------------------

 // This part of code is used to define spell constants per level
 function SummonSkeletons_Setup() {
  // Default: Level 1 = 'ndr1'
  // Default: Level 2 = 'ndr2'
  // Default: Level 3 = 'ndr3'
  SKELETONS_TYPE_ID[01]     = 'ndr1';
  SKELETONS_TYPE_ID[02]     = 'ndr2';
  SKELETONS_TYPE_ID[03]     = 'ndr3';
  
  // Default: Level 1 = 50.
  // Default: Level 2 = 50.
  // Default: Level 3 = 50.
  SKELETONS_LIFESPAN[01]     = 50.;
  SKELETONS_LIFESPAN[02]     = 50.;
  SKELETONS_LIFESPAN[03]     = 50.;
  
  // Default: Level 1 = 230 RGB
  // Default: Level 2 = 200 RGB
  // Default: Level 3 = 150 RGB
  SKELETONS_TYPE_COLOR_RED [01]  = 230;
  SKELETONS_TYPE_COLOR_GREEN [01]  = 230;
  SKELETONS_TYPE_COLOR_BLUE [01]  = 230;
  SKELETONS_TYPE_COLOR_RED [02]  = 200;
  SKELETONS_TYPE_COLOR_GREEN [02]  = 200;
  SKELETONS_TYPE_COLOR_BLUE [02]  = 200;
  SKELETONS_TYPE_COLOR_RED [03]  = 150;
  SKELETONS_TYPE_COLOR_GREEN [03]  = 150;
  SKELETONS_TYPE_COLOR_BLUE [03]  = 150;
  
  // Default: Level 1 = 4
  // Default: Level 2 = 5
  // Default: Level 3 = 6
  SKELETONS_COUNT[01]     = 4;
  SKELETONS_COUNT[02]     = 5;
  SKELETONS_COUNT[03]     = 6;
  
  // * Max skeleton rise distance from caster
  // Default: Level 1 = 400.
  // Default: Level 2 = 400.
  // Default: Level 3 = 400.
  SKELETONS_MAX_RISE_DISTANCE[01]  = 400.;
  SKELETONS_MAX_RISE_DISTANCE[02]  = 400.;
  SKELETONS_MAX_RISE_DISTANCE[03]  = 400.;
  
  // Default: Level 1 = 0.9
  // Default: Level 2 = 1.1
  // Default: Level 3 = 1.3
  SUMMON_SKELETONS_RISE_GRAVE_SIZE[01] = 0.9;
  SUMMON_SKELETONS_RISE_GRAVE_SIZE[02] = 1.1;
  SUMMON_SKELETONS_RISE_GRAVE_SIZE[03] = 1.3;
 }
 
 // *****************************************************************************************
 //        === Main Code  ===
 // *****************************************************************************************
 
 type cluster  extends  effect[06];
 
 struct fadeskel {
  unit u;
  integer lvl;
  real trans;
  real rate, e_trans, dur;
   
  static constant real INTERVAL = .1;
 }
  
 // *** fadeskels unit over time ***
 function DDFadeSkel(unit u, integer lvl) {
  fadeskel f = fadeskel.create();
   
  f.u = u;
  f.lvl = lvl;
  f.trans = (100.-SUMMON_SKELETONS_START_TRANSPARENCY)*2.55;
  f.rate = ((255.-f.trans)/SUMMON_SKELETONS_RISE_TIME)*fadeskel.INTERVAL;
  f.dur = SUMMON_SKELETONS_RISE_TIME;
   
  PauseUnit(u, true);
  SetUnitAnimation(u, SUMMON_SKELETONS_RISE_ANIMATION);
  SetUnitVertexColor(f.u,
         SKELETONS_TYPE_COLOR_RED[lvl],
         SKELETONS_TYPE_COLOR_GREEN[lvl],
         SKELETONS_TYPE_COLOR_BLUE[lvl],
         R2I(f.trans));
  // --- Start thread ---
  DDStartTim(fadeskel.INTERVAL, true, f, function() {
   fadeskel f = DDTimData();
    
   f.trans += f.rate;
   f.dur -= fadeskel.INTERVAL;
   SetUnitVertexColor(f.u,
          SKELETONS_TYPE_COLOR_RED[f.lvl],
          SKELETONS_TYPE_COLOR_GREEN[f.lvl],
          SKELETONS_TYPE_COLOR_BLUE[f.lvl],
          R2I(f.trans));
    
   if (f.dur < 0.) {
    PauseUnit(f.u, false);
    SetUnitAnimation(f.u, "stand");
    SetUnitVertexColor(f.u,
          SKELETONS_TYPE_COLOR_RED[f.lvl],
          SKELETONS_TYPE_COLOR_GREEN[f.lvl],
          SKELETONS_TYPE_COLOR_BLUE[f.lvl],
          255);
    f.u = null;
    f.destroy();
    DDQuitTim();
   }
  });
 }
 
 struct data {
  player p;
  real fac;
  real x, y;
  integer lvl, ns;
  integer nskels;
  unit sk[33];
  p_real vec;
  
  static boolean DestsFlag = false;
 }
 /*
 struct blightdata {
  integer tt, tv;
  real x, y;
 }*/
 
 function onInit() {
  trigger t = CreateTrigger();
  
  SummonSkeletons_Setup();
  
  TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT);
  TriggerAddCondition(t, Condition(function() -> boolean {
   data d;
   integer i;
   unit u;
   
   if (GetSpellAbilityId() != ABILITY_SUMMON_SKELETONS)
    return false;
   
   d = data.create();
   u = GetTriggerUnit();
   d.p = GetOwningPlayer(u);
   d.fac = GetUnitFacing(u);
   d.x = GetWidgetX(u); d.y = GetWidgetY(u);
   d.lvl = GetUnitAbilityLevel(u, ABILITY_SUMMON_SKELETONS);
   d.vec = p_real.create();
   d.nskels = 00;
   
   DestroyEffect(AddSpecialEffectTarget(SUMMON_SKELETON_CASTER_EFFECT, u, "origin"));
   
   DDStartTim(SUMMON_SKELETONS_INTERVAL, true, d, function() {
    data d = DDTimData();
    real dist, cdist, rad;
    boolean skeleton_pathing_invalid;
    real x, y;
    real vx, vy;
    unit sk;
    effect e;
    //blightdata bd;
    cluster cl;
    integer i;
    
    do {
     //skeleton_pathing_invalid = true;
     //dist = GetRandomReal(SKELETONS_MIN_RISE_DISTANCE, SKELETONS_MAX_RISE_DISTANCE[d.lvl]);
     //rad = GetRandomReal(0., bj_PI*2.);
     
     dist = DDGetRndReal(SKELETONS_MIN_RISE_DISTANCE, SKELETONS_MAX_RISE_DISTANCE[d.lvl]);
     rad = GetRandomReal(0., 2.*bj_PI);
     
     
     if (d.nskels > 00) {
      for(i=00; i < d.nskels; i+=01) {
       if (IsUnitInRangeXY(d.sk[i], d.x + dist * Cos(rad), d.y + dist * Sin(rad), SKELETONS_MIN_SPAWN_RANGE)) {
        //dist = SquareRoot(DDGetRndReal(Pw_2(SKELETONS_MIN_RISE_DISTANCE), Pw_2(SKELETONS_MAX_RISE_DISTANCE[d.lvl])));
        //dist = GetRandomReal(SKELETONS_MIN_RISE_DISTANCE, SKELETONS_MAX_RISE_DISTANCE[d.lvl]);
        //rad = GetRandomReal(0., bj_PI*2.);
        dist = DDGetRndReal(SKELETONS_MIN_RISE_DISTANCE, SKELETONS_MAX_RISE_DISTANCE[d.lvl]);
        rad = GetRandomReal(0., 2.*bj_PI);
        i = -01;
       }
      }
     }
     
     cdist = 0.;
     x = d.x; y = d.y;
     vx = 64.*Cos(rad); vy = 64.*Sin(rad);
     
     do {
      cdist += 64.;
      x += vx; y += vy;
      data.DestsFlag = false;
      d.vec[00] = x; d.vec[01] = y;
      DDEnumDestsInRange(d.vec, bj_CELLWIDTH, null, function() { data.DestsFlag = true; });
      skeleton_pathing_invalid = IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) || IsTerrainPathable(x, y, PATHING_TYPE_AMPHIBIOUSPATHING) || data.DestsFlag;
      //if (skeleton_pathing_invalid)
       //break;
     } while(cdist < dist+64. && !skeleton_pathing_invalid);
    } while(skeleton_pathing_invalid);
    
    x = d.x + dist * Cos(rad);
    y = d.y + dist * Sin(rad);
    sk = CreateUnit(d.p, SKELETONS_TYPE_ID[d.lvl], x, y, d.fac);
    d.sk[d.nskels] = sk;
    cl = cluster.create();
    cl[00] = AddSpecialEffectTarget(SUMMON_SKELETONS_FIRE_EFFECT, sk, SUMMON_SKELETONS_FIRE_EFFECT_ATTACH_1);
    cl[01] = AddSpecialEffectTarget(SUMMON_SKELETONS_FIRE_EFFECT, sk, SUMMON_SKELETONS_FIRE_EFFECT_ATTACH_2);
    cl[02] = AddSpecialEffectTarget(SUMMON_SKELETONS_FIRE_EFFECT, sk, SUMMON_SKELETONS_FIRE_EFFECT_ATTACH_3);
    cl[03] = AddSpecialEffectTarget(SUMMON_SKELETONS_FIRE_EFFECT, sk, SUMMON_SKELETONS_FIRE_EFFECT_ATTACH_4);
    cl[04] = AddSpecialEffectTarget(SUMMON_SKELETONS_FIRE_EFFECT, sk, SUMMON_SKELETONS_FIRE_EFFECT_ATTACH_5);
    cl[05] = AddSpecialEffectTarget(SUMMON_SKELETONS_FIRE_EFFECT, sk, SUMMON_SKELETONS_FIRE_EFFECT_ATTACH_6);
    DDStartTim(SKELETONS_LIFESPAN[d.lvl], false, cl, function() {
     cluster cl = DDTimData();
     DestroyEffect(cl[00]); cl[00] = null;
     DestroyEffect(cl[01]); cl[01] = null;
     DestroyEffect(cl[02]); cl[02] = null;
     DestroyEffect(cl[03]); cl[03] = null;
     DestroyEffect(cl[04]); cl[04] = null;
     DestroyEffect(cl[05]); cl[05] = null;
     cl.destroy();
     DDQuitTim();
    });
    UnitApplyTimedLife(sk, 'Brai', SKELETONS_LIFESPAN[d.lvl]);
    DestroyEffect(AddSpecialEffectTarget(SUMMON_SKELETON_RISE_EFFECT, sk, "origin"));
    DestroyEffect(AddSpecialEffectTarget(SUMMON_SKELETON_RISE_EFFECT_EX, sk, "origin"));
    e = AddSpecialEffect(SUMMON_SKELETON_GROUND_EFFECT, x, y);
    BlzSetSpecialEffectZ(e, DDTerrZ(x, y) + SUMMON_SKELETON_GROUND_EFFECT_HEIGHT);
    BlzSetSpecialEffectScale(e, SUMMON_SKELETON_GROUND_EFFECT_SIZE);
    DDDestroyEffectTimed(e, SUMMON_SKELETONS_RISE_GRAVE_DURATION);
    DDFadeSkel(sk, d.lvl);
    sk = null;
    
    
    /*
    bd = blightdata.create();
    bd.x = x; bd.y = y;
    bd.tt = GetTerrainType(x, y);
    bd.tv = GetTerrainVariance(x, y);
    SetTerrainType(bd.x, bd.y, 'Jdtr', 00, 01, 01);
    //SetBlightPoint(Player(00), x, y, true);
    DDStartTim(SUMMON_SKELETONS_BLIGHT_DURATION, false, bd, function() {
     blightdata bd = DDTimData();
     //SetBlightPoint(Player(00), bd.x, bd.y, false);
     SetTerrainType(bd.x, bd.y, bd.tt, bd.tv, 01, 01);
     bd.destroy();
     DDQuitTim();
    });*/
    
    
    //DDDestroyEffectTimed(e, SUMMON_SKELETONS_RISE_GRAVE_DURATION);
    
    x -= SUMMON_SKELETONS_RISE_GRAVE_DISTANCE_OFFSET * Cos(d.fac*bj_DEGTORAD);
    y -= SUMMON_SKELETONS_RISE_GRAVE_DISTANCE_OFFSET * Sin(d.fac*bj_DEGTORAD);
    e = AddSpecialEffect(SUMMON_SKELETONS_RISE_GRAVE_EFFECT, x, y);
    BlzSetSpecialEffectRoll(e, (d.fac+SUMMON_SKELETONS_RISE_GRAVE_EFFECT_FACING_OFFSET)*bj_DEGTORAD);
    BlzSetSpecialEffectScale(e, SUMMON_SKELETONS_RISE_GRAVE_SIZE[d.lvl]);
    DDDestroyEffectTimed(e, SUMMON_SKELETONS_RISE_GRAVE_DURATION);
    e = null;
    
    d.nskels += 01;
    if (d.nskels == SKELETONS_COUNT[d.lvl]) {
     while(d.nskels > 00) {
      d.nskels -= 01;
      d.sk[d.nskels] = null;
     }
     d.vec.destroy();
     d.destroy();
     DDQuitTim();
    }
    
   });
   
   return false;
  }));
 }

}
//! endzinc



Terror Blade

Gives a n% chance per attack to corrupt the target with attackers hate for his enemies, reducing armor, damage and dealing extra damage on activation. This ability cant trigger if target is already effected.

JASS:
//TESH.scrollpos=0
//TESH.alwaysfold=0
//**************************************************************************************
//                            Spell: Terror Blade
//                            Author: Dark Dragon
//                            Date: 8 June 2009
//
//
//                              Installation:
//
//
// - 1. Made on Warcraft III v1.30
// - 2. Go to Import Manager (F12) and extract icons: BTNTerrorBlade.blp, DISBTN, PAS and DISPAS versions
// - 3. Import all of this to your map and set there path to as you can see here (in my map)
// - 4. Go to Object Manager (F6) and copy:
//  abilities: Terror Blade and Terror Blade Effect
//  buffs: Terror Blade (Buff)
//  When you are pasting them to your map make sure you
//      type the following rawcodes:
//  Terror Blade:           'Trbl'
//  Terror Blade Effect:    'Tble'
//      Terror Blade (Buff):    'Btbl'
// - 5. If you want different raw codes you must edit them below as well:
// - 6. Edit data below to your own will and enjoy!
// - 7. And of course copy 'this trigger' and 'DD Library' to your map.
//
//**************************************************************************************



// ======================================================================
// * Spell: Terror Blade
//  * Library Load (Whole code that spell needs is inside the library)
// ======================================================================
//! zinc
library TerrorBlade requires DDLib
{
 
 // ---------------------------------------------------------------------
 //
 //   *** MAIN SPELL CONSTANTS SETUP VALUES ***
 //
 //
 // * The following values are for you to modifly for your own needs
 // * Below are constants and after that are level data values
 // * Modify all of them as you want!
 // ---------------------------------------------------------------------
 
 // --------------------------------------------
 //     *** Global Constants Scope ***
 // --------------------------------------------
 // --- The raw code of spell ---
 // Default: Trbl
 constant  integer     ABILITY_TERROR_BLADE      = 'Trbl';
  
 // --- The raw code of the spells dummy effect ---
 // Default: Tble
 constant integer     ABILITY_TERROR_BLADE_DUMMY     = 'Tble';
 
 // --- Dummy ability order string ---
 // Default: innerfire
 constant string     ABILITY_TERROR_BLADE_DUMMY_ORDER   = "innerfire";
  
 // --- The raw code of buff ---
 // Default: Btbl
 constant integer     ABILITY_TERROR_BLADE_BUFF     = 'Btbl';
 
 // --- The corruption effect path ---
 // Default: Abilities\\Spells\\Other\\HowlOfTerror\\HowlTarget.mdl
 constant string     TARGET_ATTACHMENT_EFFECT_PATH    = "Abilities\\Spells\\Other\\HowlOfTerror\\HowlTarget.mdl";

 // --- The darkness effect path ---
 // Default: Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl
 //constant string     DARKNESS_EFFECT        = "Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl";
  
 // --- This is the terror movement effect path ---
 // Default: Abilities\\Spells\\Other\\HowlOfTerror\\HowlCaster.mdl
 constant string     TERROR_BLADE_WAVE_EFFECT_PATH    = "Abilities\\Spells\\Other\\HowlOfTerror\\HowlCaster.mdl";
 
 // --- Terror wave effect z offset ---
 // Default: 65
 constant real     TERROR_BLADE_WAVE_HEIGHT     = 65.;
 
 // --- Terrors effect size in percentage ---
 // Default: 100
 constant real     TERROR_BLADE_WAVE_SIZE      = 1.;
 
 // --- Terror effects speed in coordinates per second ---
 // Default: 475
 constant real     TERROR_BLADE_WAVE_SPEED      = 475.;
 
 // --- Terror effects travel distance ---
 // Default: 200
 constant real     TERROR_BLADE_WAVE_DISTANCE     = 200.;
  
 // --- Tells can this spell be triggered even if target is already effected ---
 // Default: false
 constant boolean     CAN_TRIGGER_AT_SAME_TIME     = false;
  
 // --- Can this spell effect undead-units ---
 // Default: true
 constant boolean     CAN_EFFECT_UNDEAD_UNITS      = true;
  
 // --- Show floating text ---
 // Default: true
 constant boolean     SHOW_FLOATING_TEXT       = true;
 
 // --- How long floating text lasts in seconds ---
 // Default: 5.0
 constant real     FLOATING_TEXT_DURATION      = 5.;
  
 // --- Where is an effect attached on caster ---
 // Default: weapon
 //constant string     CASTER_ATTACH_POINT       = "weapon";
 
 // --------------------------------------------------------------------
 // * Level data do not edit here edit them below in function setup *
 //
 // { 
   real   TERROR_DURATION[];
   integer   TERROR_CHANCE[];
   real   TERROR_EXTRA_DAMAGE[];
   
   // *** Special non-level data ***
   string    TARGET_ATTACH_POINT[];
   real   FT_COLOR[];
 // }
 
 // -------------------------------------------------------------
 //  *** Level data is configured here ***
 // -------------------------------------------------------------
 function TerrorBladeLevel_Setup() {
  // --- This is duration (how long the effect lasts per level) ---
  // Default: 10 / 10 / 10
  TERROR_DURATION[01] = 10.;
  TERROR_DURATION[02] = 10.;
  TERROR_DURATION[03] = 10.;
  
  // --- Extra damage per level on triggering ---
  // Default: 20 / 35 / 50
  TERROR_EXTRA_DAMAGE[01] = 20.;
  TERROR_EXTRA_DAMAGE[02] = 35.;
  TERROR_EXTRA_DAMAGE[03] = 50.;
  
  // --- Chance in percentage to trigger this ability per level ---
  // Default: 25 / 30 / 30
  TERROR_CHANCE[01] = 25;
  TERROR_CHANCE[02] = 30;
  TERROR_CHANCE[03] = 30;
  
  // -----------------------------------------
  // --- Special non-level multiple data ---
  // -----------------------------------------
  
  // --- Attach points on target unit ---
  // --- Number of effects attached to target depend ---
  // --- on how much attach points u add here ---
  // Default: origin, weapon...
  TARGET_ATTACH_POINT[01] = "origin";
  TARGET_ATTACH_POINT[02] = "weapon";
  //set TargetAPoint[3] = "head" ...
  
  // --- This is the color of floating text ---
        // --- This has no effect if 'SHOW_FLOATING_TEXT' is off ---
        // --- Args: Red / Green / Blue / Transparency
  // Default: 60 / 13 / 40 / 0
  FT_COLOR[00] = 60.;
  FT_COLOR[01] = 13.;
  FT_COLOR[02] = 40.;
  FT_COLOR[03] = 0.;
  
 }
 
 // * 
 function TerrorBladeFilter(unit victim, player attackerPlayer) -> boolean {
  static if (!CAN_EFFECT_UNDEAD_UNITS) {
   return !IsUnitType(victim, UNIT_TYPE_MECHANICAL)    &&
       !IsUnitType(victim, UNIT_TYPE_STRUCTURE)     &&
       !IsUnitType(victim, UNIT_TYPE_ANCIENT)     &&
       !IsUnitType(victim, UNIT_TYPE_MAGIC_IMMUNE)    &&
       !IsUnitType(victim, UNIT_TYPE_UNDEAD)     &&
       !IsUnitType(victim, UNIT_TYPE_FLYING)     &&
       IsUnitEnemy(victim, attackerPlayer)      &&
       !DDIsUnitWard(victim);
  } else {
   return !IsUnitType(victim, UNIT_TYPE_MECHANICAL)    &&
       !IsUnitType(victim, UNIT_TYPE_STRUCTURE)     &&
       !IsUnitType(victim, UNIT_TYPE_ANCIENT)     &&
       !IsUnitType(victim, UNIT_TYPE_MAGIC_IMMUNE)    &&
       !IsUnitType(victim, UNIT_TYPE_FLYING)     &&
       IsUnitEnemy(victim, attackerPlayer)      &&
       !DDIsUnitWard(victim);
  }    
 }
 
 
 // ==============================================================================
 //    *** DO NOT EDIT BELOW IF YOU DONT KNOW JASS ***
 // ==============================================================================
 
 real UnitAttackTime[];
 real UnitAttackElapsedTime[];
 
 struct data {
  ddeffect wave;
  real x, y, dx, dy;
  real dist;
 }
 
 struct terrorized {
  unit v, dmy;
  effect e[02];
  real dur;
  boolean osuccess;
 }
 
 function onInit() {
  trigger t = CreateTrigger();
  
  TerrorBladeLevel_Setup();
  
  TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED);
  DDTriggerRegisterAnyUnitDamaged(t);
  TriggerAddCondition(t, Condition(function() -> boolean {
   unit u, v;
   integer id;
   real at_t;
   integer lvl;
   data d;
   real rad;
   terrorized t;
   integer ch;
   
   if (GetTriggerEventId() == EVENT_PLAYER_UNIT_ATTACKED) {
    if (GetUnitAbilityLevel(GetAttacker(), ABILITY_TERROR_BLADE) > 00)
     UnitAttackTime[H2ID(GetAttacker())] = DDGetGameElapsedTime();
    return false;
   }
   
   u = GetEventDamageSource();
   lvl = GetUnitAbilityLevel(u, ABILITY_TERROR_BLADE);
   if (lvl > 00) {
    id = H2ID(u);
    at_t = DDGetGameElapsedTime()-UnitAttackTime[id];
    
    /*DDMsg(R2S(at_t));
    DDMsg(R2S(UnitAttackElapsedTime[(id*04)+01]));
    DDMsg(R2S(UnitAttackElapsedTime[(id*04)+02]));
    DDMsg(R2S(UnitAttackElapsedTime[(id*04)+03]));*/
    
    // *** Is melee damage?
    if (R2I(at_t/.05)            == R2I(UnitAttackElapsedTime[(id*04)+01]/.05) &&
     R2I(UnitAttackElapsedTime[(id*04)+01]/.05) == R2I(UnitAttackElapsedTime[(id*04)+02]/.05) &&
     R2I(UnitAttackElapsedTime[(id*04)+02]/.05) == R2I(UnitAttackElapsedTime[(id*04)+03]/.05))
    {
     if (DDGetRndInt(01, 100) <= TERROR_CHANCE[lvl]) {
      v = GetTriggerUnit();
      static if (!CAN_TRIGGER_AT_SAME_TIME)
       if (GetUnitAbilityLevel(v, ABILITY_TERROR_BLADE_BUFF) > 00) {
        u = null; v = null;
        UnitAttackElapsedTime[ (id*04) + R2I(UnitAttackElapsedTime[(id*04)]) ] = at_t;
        UnitAttackElapsedTime[(id*04)] += 1.;
        if (UnitAttackElapsedTime[(id*04)] == 4.) UnitAttackElapsedTime[(id*04)] = 0.;
        return false;
       }
      
      if (TerrorBladeFilter(v, GetOwningPlayer(u))) {
       d = data.create();
       d.x = GetWidgetX(u); d.y = GetWidgetY(u);
       d.wave = ddeffect.createZ(TERROR_BLADE_WAVE_EFFECT_PATH, d.x, d.y, DDTerrZ(d.x, d.y) + TERROR_BLADE_WAVE_HEIGHT, DDGetRndReal(0., bj_PI*2.), TERROR_BLADE_WAVE_SIZE);
       rad = Atan2(GetWidgetY(v)-d.y, GetWidgetX(v)-d.x);
       d.dx = TERROR_BLADE_WAVE_SPEED*DD_INTERVAL*Cos(rad);
       d.dy = TERROR_BLADE_WAVE_SPEED*DD_INTERVAL*Sin(rad);
       d.dist = TERROR_BLADE_WAVE_DISTANCE;
       
       DDStartTim(DD_INTERVAL, true, d, function() {
        data d = DDTimData();
        
        d.wave.Position(d.wave.X + d.dx, d.wave.Y + d.dy);
        
        d.dist -= TERROR_BLADE_WAVE_SPEED*DD_INTERVAL;
        if (d.dist < 0.) {
         d.wave.destroy();
         d.destroy();
         DDQuitTim();
        }
       });
       BlzSetEventDamage(GetEventDamage() + TERROR_EXTRA_DAMAGE[lvl]);
       //UnitDamageTarget(u, v, TERROR_EXTRA_DAMAGE[lvl], true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS);
       static if (SHOW_FLOATING_TEXT)
        DDNewTextTagUnit(v, I2S(R2I(TERROR_EXTRA_DAMAGE[lvl]))+"!", FLOATING_TEXT_DURATION, FT_COLOR[00], FT_COLOR[01], FT_COLOR[02], FT_COLOR[03]);
       
       t = terrorized.create();
       t.v = v;
       t.e[00] = AddSpecialEffectTarget(TARGET_ATTACHMENT_EFFECT_PATH, v, TARGET_ATTACH_POINT[01]);
       t.e[01] = AddSpecialEffectTarget(TARGET_ATTACHMENT_EFFECT_PATH, v, TARGET_ATTACH_POINT[02]);
       t.dur = TERROR_DURATION[lvl];
       t.dmy = DDLoadSpellDummy(GetOwningPlayer(u), d.x, d.y, ABILITY_TERROR_BLADE_DUMMY, lvl);
       IssueTargetOrder(t.dmy, ABILITY_TERROR_BLADE_DUMMY_ORDER, v);
       DDStartTim(.1, true, t, function() {
        terrorized t = DDTimData();
        
        t.dur -= .1;
        if (t.dur > 9.)
         return;
        if (IsUnitType(t.v, UNIT_TYPE_DEAD) || t.dur < 0. || GetUnitAbilityLevel(t.v, ABILITY_TERROR_BLADE_BUFF) == 00) {
         UnitRemoveAbility(t.dmy, ABILITY_TERROR_BLADE_DUMMY);
         DDRecycleDummy(t.dmy);
         t.v = null;
         t.dmy = null;
         DestroyEffect(t.e[00]); t.e[00] = null;
         DestroyEffect(t.e[01]); t.e[01] = null;
         t.destroy();
         DDQuitTim();
        }
       });
      }
     }
    }
    UnitAttackElapsedTime[ (id*04) + R2I(UnitAttackElapsedTime[(id*04)]) ] = at_t;
    UnitAttackElapsedTime[(id*04)] += 1.;
    if (UnitAttackElapsedTime[(id*04)] == 4.) UnitAttackElapsedTime[(id*04)] = 0.;
   }
   
   u = null; v = null;
   return false;
  }));
 }
 
}
//! endzinc




[B]

Bubble Blast

Raises 'n' water orbs from the ground which will float around the caster. After short amount of time waves will fall to the ground dealing damage to any nearby enemy and remove all positive buffs from them. Any unit which was effected will be pushed away from caster.

JASS:
//TESH.scrollpos=0
//TESH.alwaysfold=0
//**************************************************************************************
//                              Installation:
//
// - 1. Made on Warcraft III v1.30
// - 2. Go to Import Manager (F12) and extract BTNWaterExhausting.blp and its DISBTN version,
//  BubbleSpawn.mdx, WaterOrb.mdx, WaterBurst.mdx
//  water_wave.wav, water_splash1.wav, water_splash2.wav, water_splash3.wav
// - 3. Import all of this to your map and set ther path to as you can see here (in my map)
// - 4. Go to Object Manager (F6) and copy "Bubble Blast" ability.
//   When you are pasting them to your map make sure you match there rawcodes with ones below
// - 5. If you want different raw codes edit the below as well
// - 6. Copy this trigger and "DD Library" to your map
// - 7. Edit data below to your own will and enjoy the spell
//
// Credits:
//  MajorSonnwaitts, Pyritie, JetFangInferno, dueeast.com (sounds)
//
//**************************************************************************************

//! zinc
library BubbleBlast requires DDLib
{
 
 // ************************************************************************************************
 //        --- Ability Constants ---
 // ************************************************************************************************
 
 constant  integer      BUBBLE_BLAST_ABILITY_ID      = 'wtex';
 constant  boolean      BUBBLE_BLAST_REMOVE_POSITIVE_BUFFS   = true;
 constant  boolean      BUBBLE_BLAST_REMOVE_NEGATIVE_BUFFS   = false;
 // Effect attached to unit on which buffs are removed and its attach point
 constant string      BUBBLE_BLAST_REMOVE_BUFFS_MODEL_PATH  = "Abilities\\Spells\\Human\\DispelMagic\\DispelMagicTarget.mdl";
 constant string      BUBBLE_BLAST_REMOVE_BUFFS_ATTACH_POINT  = "origin";
 
 
 constant boolean      USE_KNOCKBACK         = true;
 constant real      KNOCKBACK_TRAVEL_DISTANCE     = 225.;
 constant real      KNOCKBACK_TRAVEL_SPEED      = 300.;
 constant string      KNOCKBACK_TRAVEL_GROUND_DRAG_EFFECT_PATH = "Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl";
 constant string      KNOCKBACK_DRAG_EFFECT_ATTACH_POINT   = "foot";
 // How offten is 'KNOCKBACK_TRAVEL_GROUND_DRAG_EFFECT_PATH' effect created
 constant real      KNOCKBACK_TRAVEL_GROUND_DRAG_EFFECT_INTERVAL= 0.25;
 
 // ************************************************************************************************
 //        --- Effect Constants ---
 // ************************************************************************************************
 
 constant string      BUBBLE_SPAWN_MODEL_PATH      = "Spells\\BubbleBlast\\BubbleSpawn.mdx";
 constant real      BUBBLE_SPAWN_MODEL_SIZE      = 0.5;
 constant real      BUBBLE_SPAWN_MODEL_MIN_DURATION    = 7.;
 constant real      BUBBLE_SPAWN_MODEL_MAX_DURATION    = 9.;
 
 constant string      WATER_ORB_MODEL_PATH      = "Spells\\BubbleBlast\\WaterOrb.mdx";
 constant real      WATER_ORB_MODEL_SIZE      = 2.;
 constant real      WATER_ORB_TRAVEL_SPEED      = 330.;
 // Apcisa (X) direction only motion. The way ellipse works is that virtual points move around caster
 // at x-axes 'WATER_ORB_ELLIPSE_X_TRAVEL_SPEED', while y is calculated. Orb then based on its position
 // moves towards that virtual point from its current location
 constant real      WATER_ORB_ELLIPSE_X_TRAVEL_SPEED   = 190.;
 // ellipse a = value based on 'BUBBLE_SPAWN_MIN/MAX_AOE', while ellipse b = a*'WATER_ORB_ELLIPSE_FACTOR'
 constant  real      WATER_ORB_ELLIPSE_FACTOR     = 0.66;
 // gravity actiong on orb when it starts falling defined in coordinates per square second
 constant real      WATER_ORB_FALL_ACCELERATION     = 555.555;
 constant real      WATER_ORB_MIN_HEIGHT      = 100.;
 constant real      WATER_ORB_MAX_HEIGHT      = 400.;
 
 constant string      WATER_BLAST_MODEL_PATH      = "Spells\\BubbleBlast\\WaterBurst.mdx";
 constant real      WATER_BLAST_MODEL_SIZE      = 0.5;
 constant real      WATER_BLAST_MODEL_DURATION     = 1.33;
 
 constant string      WATER_BLAST_AFTEREFFECT_MODEL_PATH   = "Doodads\\Icecrown\\Water\\BubbleGeyserSteam\\BubbleGeyserSteam.mdx";
 constant real      WATER_BLAST_AFTEREFFECT_MODEL_SIZE   = 1.15;
 constant real      WATER_BLAST_AFTEREFFECT_MODEL_DURATION  = 6.5;
 
 // ************************************************************************************************
 //        --- Sounds Constants ---
 // ************************************************************************************************
 
 constant string      BUBBLE_SPWAN_START_SOUND_PATH    = "Custom\\Spells\\BubbleBlast\\water_wave.wav";
 constant real      BUBBLE_SPWAN_START_SOUND_VOLUME    = 70.;
 constant string      WATER_ORB_IMPACT_SOUND_PATH_01    = "Custom\\Spells\\BubbleBlast\\water_splash1.wav";
 constant real      WATER_ORB_IMPACT_SOUND_VOLUME_01   = 70.;
 constant string      WATER_ORB_IMPACT_SOUND_PATH_02    = "Custom\\Spells\\BubbleBlast\\water_splash2.wav";
 constant real      WATER_ORB_IMPACT_SOUND_VOLUME_02   = 70.;
 constant string      WATER_ORB_IMPACT_SOUND_PATH_03    = "Custom\\Spells\\BubbleBlast\\water_splash3.wav";
 constant real      WATER_ORB_IMPACT_SOUND_VOLUME_03   = 70.;
 constant real      SOUND_MAX_DISTANCE       = 3500.;
 
 
 
 // ---------------------------------------------------------------------
 //    "non-EDITABLE", just declarations!
 // ---------------------------------------------------------------------
 integer  BUBBLE_SPWAN_COUNT[];
 real   WATER_ORB_MIN_DURATION[], WATER_ORB_MAX_DURATION[];
 real   BUBBLE_SPAWN_MIN_AOE[], BUBBLE_SPAWN_MAX_AOE[];
 real  WATER_BLAST_DAMAGE[], WATER_BLAST_AOE[];
 // ---------------------------------------------------------------------
 
 
 function BubbleBlastLevelSetup() {
  // How much orbs are created per level?
  // Level 01 Default: 9
  // Level 02 Default: 11
  // Level 03 Default: 12
  BUBBLE_SPWAN_COUNT[01] = 9;
  BUBBLE_SPWAN_COUNT[02] = 11;
  BUBBLE_SPWAN_COUNT[03] = 12;
 
  // Within min and max range from caster, orbs and bubbles spawn!
  // Level 01 Default: MIN = 200, MAX = 400
  // Level 02 Default: MIN = 200, MAX = 450
  // Level 03 Default: MIN = 200, MAX = 500
  BUBBLE_SPAWN_MIN_AOE[01] = 200.; BUBBLE_SPAWN_MAX_AOE[01] = 400.;
  BUBBLE_SPAWN_MIN_AOE[02] = 200.; BUBBLE_SPAWN_MAX_AOE[02] = 450.;
  BUBBLE_SPAWN_MIN_AOE[03] = 200.; BUBBLE_SPAWN_MAX_AOE[03] = 500.;
 
  // Once water orbs spawn, how long does each one of them last,
  // if min and max are not equal, then each orb lasts for its own duration.
  // Level 01: Min Default: 4.5, Max Default: 6.5
  // Level 02: Min Default: 3.75, Max Default: 5.75
  // Level 03: Min Default: 2.75, Max Default: 4.5
  WATER_ORB_MIN_DURATION[01] = 4.5; WATER_ORB_MAX_DURATION[01] = 6.5;
  WATER_ORB_MIN_DURATION[02] = 3.75; WATER_ORB_MAX_DURATION[02] = 5.75;
  WATER_ORB_MIN_DURATION[03] = 2.75; WATER_ORB_MAX_DURATION[03] = 4.5;
 
  // Upon water burst explosion, how much damage is dealt?
  // Level 01 Default: 100
  // Level 02 Default: 150
  // Level 03 Default: 210
  WATER_BLAST_DAMAGE[01] = 100.;
  WATER_BLAST_DAMAGE[02] = 150.;
  WATER_BLAST_DAMAGE[03] = 210.;
 
  // Upon water burst explosion, what is the radius in which units are damaged?
  // Level 01 Default: 150
  // Level 02 Default: 150
  // Level 03 Default: 150
  WATER_BLAST_AOE[01] = 150.;
  WATER_BLAST_AOE[02] = 150.;
  WATER_BLAST_AOE[03] = 150.;
 }
 
 // *** Which units should be damaged? '!' represents not / inverted
 function WaterBlastUnitFilter(unit f, player castingPlayer) -> boolean {
  return !IsUnitType(f, UNIT_TYPE_STRUCTURE)    &&
      !IsUnitType(f, UNIT_TYPE_DEAD)     &&
      !IsUnitType(f, UNIT_TYPE_MAGIC_IMMUNE)   &&
      !IsUnitType(f, UNIT_TYPE_MECHANICAL)    &&
      !IsUnitType(f, UNIT_TYPE_FLYING)     &&
      IsUnitEnemy(f, castingPlayer)     &&
      !BlzIsUnitInvulnerable(f)      &&
      !DDIsUnitWard(f);
 }
 
 // ===========================================================================================
 //    ***************************************************************
 //       *** Spell Code | "non-EDITABLE" ***
 //    ***************************************************************
 // ===========================================================================================
 
 /*public function testAA(unit f) {
  if (IsUnitType(f, UNIT_TYPE_FLYING))
   DDMsg("a");
  if (IsUnitType(f, UNIT_TYPE_MAGIC_IMMUNE))
   DDMsg("b");
  if (BlzIsUnitInvulnerable(f))
   DDMsg("c");
 }*/
 
 struct knockback {
  unit u;
  real tim=0.;
  real dist, spd, dx, dy;
 
  static boolean Flag[];
 }
 
 struct waterorb {
  unit u;
  ddeffect orb;
  integer lvl;
  real el_x, el_y, z;
  real x_spd, y_sign, rad_offset;
  real a, b;
  real dur;
 
  method destroy() {
   u = null;
   orb.destroy();
   deallocate();
  }
 
  method GetCoords() {
   el_x += x_spd;
   if (x_spd > 0.) {
    if (el_x > a) {
     x_spd = -x_spd;
     y_sign = -y_sign;
    }
   } else {
    if (el_x < -a) {
     x_spd = -x_spd;
     y_sign = -y_sign;
    }
   }
   el_y = b*y_sign*SquareRoot(1.-Pw_2(el_x/a));
  }
 
  method ApplyMotion() {
   real x, y;
   real dist;
 
   this.GetCoords();
   x = GetWidgetX(u);
   y = GetWidgetY(u);
 
   x += el_x * Cos(rad_offset);
   y += el_x * Sin(rad_offset);
 
   x += el_y * Cos(rad_offset+(bj_PI/2.));
   y += el_y * Sin(rad_offset+(bj_PI/2.));
 
   //rad = Atan2(y-orb.Y, x-orb.X);
   dist = SquareRoot(DDHypot(x-orb.X, y-orb.Y) + Pw_2(z-orb.Z));
   orb.PositionZ(orb.X + (WATER_ORB_TRAVEL_SPEED*DD_INTERVAL*((x-orb.X)/dist)),
        orb.Y + (WATER_ORB_TRAVEL_SPEED*DD_INTERVAL*((y-orb.Y)/dist)),
        orb.Z + (WATER_ORB_TRAVEL_SPEED*DD_INTERVAL*((z-orb.Z)/dist)));
  }
 
  method ApplyFall() {
   x_spd += WATER_ORB_FALL_ACCELERATION*DD_INTERVAL*DD_INTERVAL;
   orb.Z -= x_spd;
  }
 
  method OrbDetonate() {
   integer rnd_snd = DDGetRndInt(01, 03);
   effect e;
 
   if (rnd_snd == 01)
    DDGenericSound(WATER_ORB_IMPACT_SOUND_PATH_01, WATER_ORB_IMPACT_SOUND_VOLUME_01, orb.X, orb.Y, SOUND_MAX_DISTANCE, 1.);
   else if (rnd_snd == 02)
    DDGenericSound(WATER_ORB_IMPACT_SOUND_PATH_02, WATER_ORB_IMPACT_SOUND_VOLUME_02, orb.X, orb.Y, SOUND_MAX_DISTANCE, 1.);
   else
    DDGenericSound(WATER_ORB_IMPACT_SOUND_PATH_03, WATER_ORB_IMPACT_SOUND_VOLUME_03, orb.X, orb.Y, SOUND_MAX_DISTANCE, 1.);
 
   e = AddSpecialEffect(WATER_BLAST_MODEL_PATH, orb.X, orb.Y);
   BlzPlaySpecialEffect(e, ANIM_TYPE_STAND);
   BlzSetSpecialEffectScale(e, WATER_BLAST_MODEL_SIZE);
   DDDestroyEffectTimed(e, WATER_BLAST_MODEL_DURATION);
 
   e = AddSpecialEffect(WATER_BLAST_AFTEREFFECT_MODEL_PATH, orb.X, orb.Y);
   BlzSetSpecialEffectScale(e, WATER_BLAST_AFTEREFFECT_MODEL_SIZE);
   DDDestroyEffectTimed(e, WATER_BLAST_AFTEREFFECT_MODEL_DURATION); e = null;
 
   DDGroupFilterArea(orb.X, orb.Y, WATER_BLAST_AOE[lvl], this, function() {
    waterorb wo = DDGFilterData();
    unit f = GetFilterUnit();
    knockback kb;
    real rad;
 
    if (WaterBlastUnitFilter(f, GetOwningPlayer(wo.u))) {
     UnitRemoveBuffs(f, BUBBLE_BLAST_REMOVE_POSITIVE_BUFFS, BUBBLE_BLAST_REMOVE_NEGATIVE_BUFFS);
     //bj_lastCreatedUnit = DDLoadDummy();
     DDSpellDamage(wo.u, f, WATER_BLAST_DAMAGE[wo.lvl]);
     //DDSpellDamage(bj_lastCreatedUnit, f, WATER_BLAST_DAMAGE[wo.lvl]);
     //DDRecycleDummy(bj_lastCreatedUnit);
     DestroyEffect(AddSpecialEffectTarget(BUBBLE_BLAST_REMOVE_BUFFS_MODEL_PATH, f, BUBBLE_BLAST_REMOVE_BUFFS_ATTACH_POINT));
  
     static if (USE_KNOCKBACK) {
      if (knockback.Flag[H2ID(f)]) {
       f = null;
       return;
      }
   
      knockback.Flag[H2ID(f)] = true;
      kb = knockback.create();
      PauseUnit(f, true);
      kb.u = f;
      kb.dist = KNOCKBACK_TRAVEL_DISTANCE;
      kb.spd = KNOCKBACK_TRAVEL_SPEED*DD_INTERVAL;
      rad = Atan2(GetWidgetY(f)-GetWidgetY(wo.u), GetWidgetX(f)-GetWidgetX(wo.u));
      kb.dx = kb.spd * Cos(rad);
      kb.dy = kb.spd * Sin(rad);
      DDStartTim(DD_INTERVAL, true, kb, function() {
       knockback kb = DDTimData();
    
       kb.tim += DD_INTERVAL;
       if (ModuloReal(kb.tim, KNOCKBACK_TRAVEL_GROUND_DRAG_EFFECT_INTERVAL) <= DD_INTERVAL)
        DestroyEffect(AddSpecialEffectTarget(KNOCKBACK_TRAVEL_GROUND_DRAG_EFFECT_PATH, kb.u, KNOCKBACK_DRAG_EFFECT_ATTACH_POINT));
    
       SetUnitPosition(kb.u, GetWidgetX(kb.u) + kb.dx, GetWidgetY(kb.u) + kb.dy);
    
       kb.dist -= kb.spd;
       if (kb.dist < 0.) {
        knockback.Flag[H2ID(kb.u)] = false;
        PauseUnit(kb.u, false);
        kb.u = null;
        kb.destroy();
        DDQuitTim();
       }
      });
     }
    }
 
    f = null;
   });
  }
 
 }
 
 //b*sqrt(1-(x/a)^2) = y
 function onInit() {
  trigger t = CreateTrigger();
 
  BubbleBlastLevelSetup();
 
  TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT);
  TriggerAddCondition(t, Condition(function() -> boolean {
   unit u;
   integer i, lvl;
   effect e;
   real x, y, tx, ty;
   real dist, rad;
   waterorb wo;
 
   if (GetSpellAbilityId() != BUBBLE_BLAST_ABILITY_ID)
    return false;
 
   u = GetTriggerUnit();
   x = GetWidgetX(u);
   y = GetWidgetY(u);
   lvl = GetUnitAbilityLevel(u, BUBBLE_BLAST_ABILITY_ID);
 
   DDGenericSound(BUBBLE_SPWAN_START_SOUND_PATH, BUBBLE_SPWAN_START_SOUND_VOLUME, x, y, SOUND_MAX_DISTANCE, 1.);
 
   for(i=00; i < BUBBLE_SPWAN_COUNT[lvl]; i+=01) {
    dist = DDGetRndReal(BUBBLE_SPAWN_MIN_AOE[lvl], BUBBLE_SPAWN_MAX_AOE[lvl]);
    rad = GetRandomReal(0., 2.*bj_PI);
    tx = x + dist * Cos(rad);
    ty = y + dist * Sin(rad);
    e = AddSpecialEffect(BUBBLE_SPAWN_MODEL_PATH, tx, ty);
    BlzSetSpecialEffectScale(e, BUBBLE_SPAWN_MODEL_SIZE);
    DDDestroyEffectTimed(e, DDGetRndReal(BUBBLE_SPAWN_MODEL_MIN_DURATION, BUBBLE_SPAWN_MODEL_MAX_DURATION));
 
    wo = waterorb.create();
    wo.u = u;
    wo.orb = ddeffect.create(WATER_ORB_MODEL_PATH, tx, ty, GetRandomReal(0., 2.*bj_PI), WATER_ORB_MODEL_SIZE);
    wo.a = dist; wo.b = dist*WATER_ORB_ELLIPSE_FACTOR;
    wo.rad_offset = rad;
    wo.y_sign = 1.; if (GetRandomInt(00, 01) == 01) wo.y_sign = -1.;
    wo.x_spd = -WATER_ORB_ELLIPSE_X_TRAVEL_SPEED*DD_INTERVAL;
    wo.z = DDTerrZ(tx, ty) + DDGetRndReal(WATER_ORB_MIN_HEIGHT, WATER_ORB_MAX_HEIGHT);
    wo.dur = DDGetRndReal(WATER_ORB_MIN_DURATION[lvl], WATER_ORB_MAX_DURATION[lvl]);
    wo.lvl = lvl;
 
    DDStartTim(DD_INTERVAL, true, wo, function() {
     waterorb wo = DDTimData();
  
     if (wo.dur > 0. && !IsUnitType(wo.u, UNIT_TYPE_DEAD)) {
      wo.ApplyMotion();
      wo.dur -= DD_INTERVAL;
     } else {
      wo.ApplyFall();
      if (wo.orb.Z < 5.) {
       wo.OrbDetonate();
       wo.destroy();
       DDQuitTim();
      }
     }
    });
   }
 
   u = null;
   e = null;
   return false;
  }));
 }
 
}
//! endzinc
[/B]





Main


Main

Crazyrussian (BTNCRFrostShock)
VaLkYroN
Tranquil
jigrael
Vexorian (JassHelper) (Dummy)
shamanyouranus
JetFangInferno (Blizzard Eruption)
Daelin (Frozen Orb)
Hueter
Anachron
SkriK
bananaHUNT
Dan van Ohllus (DvO's Winter Effects)
KelThuzad (BTNReflex)
Skizzik
Erdie
MajorSonnwaitts (BubblesBuff)
Pyritie (Water High and Uber)
PrinceYaser (BTNNecromancy)
UgoUgo (NecroticBlast)

therecordist.com
freesound.org
dueeast.com (dueeast.com/watersounds.html)

Other

Blizzard
Hive Workshop
JassNewGen Pack team.
Audacity
Notepad++

Additional:

TheBlooddancer
-JonNny
Deaod
s4nji
and every one else who helped.







Q: Does this work with default JNGP?
A: Yes

Q: It took you long to release this patch! will there be v5?
A: No, this is the last version of DDUP spell pack.

Q: Will you make a new spell pack with more spells?
A: Maybe in zinc with new libraries. That ofc is not my priority as i am currently working on campaign and that shall take me more than enough time for coding and overall making mods, spells... Still not sure but maybe ill make a new spell pack.
Currently it is unknown.

Q: Is there at least one spell in GUI?
A: No

Q: Will you convert any of spells from vjass to GUI?
A: No

Q: Are this spells only for melee maps?
A: All of spells are made as for melee maps but you can use them in any map, as they are easy to modify. They have as well "max damage" deal to configure, making sure that they are not overpowered.

Q: I dont know jass and i want to install few spells in my map, can you help?
A: Yes! there is an block of comments at beginning of every spell which tells you exactlly on how to install spell in your map.

Q: Its said that this spells are fully editable but there is no such an option!
A: This options are not in "Object Editor" ofc you must edit them in Object Editor but main spell setup is done in custom script at beginning of each spell.

Q: Ok i found that text so what to do now?
A: Each variable of this you will see can be set to your own value to completelly remake my spells to your own will. Each variable does something different and comments above them say what each value does.

Q: I want to use this spells in my map which will be for multiplayer at battle.net, are they MUI?
A: Yes

Q: I can see a lot of lines even through i dont know jass other spells usually have about 300 or less lines, is this slow?
A: Should not be, but best is to test it on your own PC

Q: I have slow CPU, low RAM... i need to decrease FPS, can i do that and how?
A: Some spells have that editable already in globals section for users. New ones do not have that there since its not a part of something that spell should change and in fact this is my own constatn which can ofc be editable by you. Go to selected spell and press Alt Gr + F -> search dialog will appear. There write TIMER_DELAY press enter. It will point you to constant value you will see it points to 0.025 which is 40 FPS. If you want to change it set it to (1 / Your FPS).

Q: Do your spells leak? Do you use AnyUnitEventBJ which leak filters?
A: No. No.






All custom code from my DD Library

JASS:
//==========================================================================
//                  Dark Dragon Library Code v1.3
//
//      * Made on Warcraft III v1.30.4
//
//  Installation:
//               
//                  1) Export instantdummy.mdx from this map and import it to your map, leave path at "war3mapImported/instantdummy.mdx"
//                  2) Copy this trigger to your map, save your map and then change below line "// external ... " or copy "DD Dummy" and paste it in your map
//     3) Copy and paste "Unit Chill" ability from this map to your map
//     4) Match the rawcodes below to your map or use same ones as below
//
// Credits:
//          ('Vexorian' - dummy.mdx)
//============================================================================

// *** Change "// external" to "//! external", save your map, close map, change back from "//!" to "//" and save map again.
// *** This will create dummy in your map
//
// ==================================
// external ObjectMerger w3u ushd dumy uabi "Aloc,Amrf" uble 0 ucbs 0 ucpt 0 umxp 0 umxr 0 umdl "war3mapImported\instantdummy.mdx" ushu "None" umvh 0 umvs 1 umas 1 umis 1 ucol 0 ufoo 0 uhom 1 umpi 10000 umpm 10000 usid 1 usin 1 unam "DD Dummy"
// ==================================


//! zinc

library DDLib requires optional TimerUtils, optional GroupUtils
{
 
    // -----------------------------------------------------------------------
    // -----------------------------------------------------------------------
    // *** Lib constants ***
    public {
     
  // ----------------------------------------------------------------------
  // * Start modify/match rawcodes to your map
        constant        integer     DD_DUMMYCODE       = 'dumy';
        constant        integer     DD_ABILITY_CROWN_FORM     = 'Amrf';
  constant   integer  DD_CHILL     = 'Achl';
  constant   integer  DD_CHILL_BUFF    = 'Bfro';
  // * End modify
  // ----------------------------------------------------------------------
 
 
  constant        integer     p_null             = (0x0);
        constant        real        DD_INTERVAL       = .017;
     
                        // map min and max coords
                        real        DDMinX             = 0.;
                        real        DDMinY             = 0.;
                        real        DDMaxX             = 0.;
                        real        DDMaxY             = 0.;
    }
 
 private {
  constant   integer  HARVEST_ID     = 'Ahrl';
  constant  real  TRIGGER_REFRESH_RATE  = (60.)*3.; /// damage detection trigger
                     
                        unit   TreeChecker              = null;
      trigger  TempTrig      = null;
      integer  NTrig       = 0;
      trigger  DmgTrig[];
      p_real   EnumVec      = p_null;
      boolexpr  EnumFilter      = null;
      sound  ErrorSound     = null;
      timer  GameElapsedTimer   = null;
  constant   integer  RND_INT_MAX_ARRAY_N   = 100;
      integer  RndInt[], RndIntWriteN = 00, RndIntReadN = 00;
      trigger  TrigMouseEvent     = null;
      force   RndGenForce     = null;
      real   RndElapsedTime     = 0.;
 }
    // -----------------------------------------------------------------------
    // -----------------------------------------------------------------------
    // -----------------------------------------------------------------------
 
    // * types
    public {
     
        // *** pointer to list of data ***
        type    p_integer           extends     integer[8];
        type    p_real              extends     real[8];
        type    p_unit              extends     unit[8];
     
  function H2ID(handle h) -> integer {
   return GetHandleId(h) - 0x100000;
  }
 
        function New_pInteger(integer i) -> p_integer
        { p_integer p = p_integer.create(); p[0] = i; return p; }
        function New_pReal(real r) -> p_real
  { p_real p = p_real.create(); p[0] = r; return p; }
        function New_pUnit(unit u) -> p_unit
  { p_unit p = p_unit.create(); p[0] = u; return p; }
     
  function pVector(real x, real y, real z) -> p_real {
   p_real v = p_real.create();
   v[0] = x; v[1] = y; v[2] = z;
   return v;
  }
 
  // --------------------------------------------------------------------------------------
 
  function DDMsg(string str) {
   DisplayTimedTextFromPlayer(GetLocalPlayer(), 0., 0., 30., str);
  }
 
  // --------------------------------------------------------------------------------------
 
  function DisplayErrorMsgPlayer(player p, real dur, string msg) {
   if (GetLocalPlayer() == p) {
    StartSound(ErrorSound);
    DisplayTimedTextFromPlayer(p, 0., 0., dur, "|cffffcc00"+ msg +"|r");
   }
  }

    }
 
    // -----------------------------------------------------------------------
    // ->           ***** private globals *****
    // -----------------------------------------------------------------------
    private {
        location    TempLoc         = Location(0., 0.);
        timer       TimerStack[];
        integer     TimN            = 0;
        group       GroupStack[];
        integer     GrpN            = 0;
        unit        DummyStack[];
        integer     DumN            = 0;
  integer  TimTicks[];
  integer  TimData[];
  timer  TimTim1[];
  timer  TimTim2[];
 
 
  integer  UnitStackData = 0;
  unit  UnitStack[];
  integer  US_N   = 0;
     
        public hashtable   DDHT            = InitHashtable();
    }
    // -----------------------------------------------------------------------
 
   public {
 
        // *** Global funcs
     
        function Pw_2(real x) -> real {
            return x*x;
        }
 
  function DDHypot(real x, real y) -> real {
   return (x*x) + (y*y);
  }
     
        function DDTerrZ(real x, real y) -> real {
            MoveLocation(TempLoc, x, y);
            return GetLocationZ(TempLoc);
        }
     
        function DDWidgetTerrZ(widget w) -> real {
   MoveLocation(TempLoc, GetWidgetX(w), GetWidgetY(w));
            return GetLocationZ(TempLoc);
        }
 
  function DDEffectTerrZ(effect e) -> real {
   MoveLocation(TempLoc, BlzGetLocalSpecialEffectX(e), BlzGetLocalSpecialEffectY(e));
            return GetLocationZ(TempLoc);
  }
 
  function DDGetUnitZ(unit u) -> real {
   return BlzGetUnitZ(u) + GetUnitFlyHeight(u);
  }
     
        // =================================================================
        //              *** Save Handle data ****
        // =================================================================
     
        function DDSet(handle h, integer id, integer val) {
            SaveInteger(DDHT, id+1, GetHandleId(h), val);
        }
     
        function DDGet(handle h, integer id) -> integer {
            return LoadInteger(DDHT, id+1, GetHandleId(h));
        }
 
  function DDHas(handle h, integer id) -> boolean {
   return HaveSavedInteger(DDHT, id+1, GetHandleId(h));
  }
 
  function DDFlush(integer id) {
   FlushChildHashtable(DDHT, id+1);
  }
     
        // =================================================================
        //              *** Timer Handling ****
        // =================================================================
 
  // -> check if timer is recycled
  function DDIsTimRecycled(timer t) -> boolean {
   integer i;
   for(i=TimN-01; i >= 00; i-=01)
    if (TimerStack[i] == t)
     return true;
   return false;
  }
 
        // -> Load timer for recycling
        function DDLoadTim() -> timer {
            static if (LIBRARY_TimerUtils) { return NewTimer(); }
            else {
                if (TimN > 0) {
                    TimN -= 1;
                    return TimerStack[TimN];
                }
                return CreateTimer();
            }
        }
     
        // -> recycle loaded timer
        function DDRecycleTim(timer t) {
            static if (LIBRARY_TimerUtils) { ReleaseTimer(t); }
            else {
    static if (DEBUG_MODE)
     if (DDIsTimRecycled(t)) {
      DDMsg("Multiple recycle of timer!");
      return;
     }
                TimerStack[TimN] = t;
                TimN += 1;
            }
        }
     
        // ** Get data stored on expired timer
        function DDTimData() -> integer {
            return TimData[H2ID(GetExpiredTimer())];
        }
 
  // *** Custom timer tick
        function DDCTimTick(timer t) -> integer {
            return TimTicks[H2ID(t)];
        }
 
  // *** Gets current tick and adds next one ***
        function DDTimTick() -> integer {
   integer id = H2ID(GetExpiredTimer());
   TimTicks[id] += 01;
            return TimTicks[id];
        }
     
        // ** start timer with data storage
        function DDStartTim(real secs, boolean looping, integer pdata, code func) -> timer {
            timer t = DDLoadTim();
 
   TimData[H2ID(t)] = pdata;
            TimerStart(t, secs, looping, func);
            return t;
        }
     
        // ** start timer with data storage, and launches it instantly
        function DDStartTimInst(real secs, boolean looping, integer pdata, code func) -> timer {
            timer t1 = DDLoadTim(), t2 = DDLoadTim(), t3 = DDLoadTim();
         
   TimData[H2ID(t2)] = pdata;
            TimerStart(t2, 0., false, func);
 
   TimTim1[H2ID(t3)] = t1;
   TimTim2[H2ID(t3)] = t2;
   TimerStart(t3, .005, false, function() {
    timer t = GetExpiredTimer();
    integer id = H2ID(t);
 
    PauseTimer(t);
    static if (LIBRARY_TimerUtils)
     ReleaseTimer(t);
    else {
     TimerStack[TimN] = t;
     TimN += 1;
    }
 
    t = TimTim2[id];
    if (DDIsTimRecycled(t))
     t = TimTim1[id];
    TimTicks[H2ID(t)] = 00;
    PauseTimer(t);
    static if (LIBRARY_TimerUtils)
     ReleaseTimer(t);
    else {
     TimerStack[TimN] = t;
     TimN += 1;
    }
   });
 
   TimData[H2ID(t1)] = pdata;
            TimerStart(t1, secs, looping, func);
         
            return t1;
        }
     
        // *** Quit expired timer ***
        function DDQuitTim() {
   timer t = GetExpiredTimer();
   TimTicks[H2ID(t)] = 00;
            PauseTimer(t);
   static if (LIBRARY_TimerUtils)
    ReleaseTimer(t);
            else {
                TimerStack[TimN] = t;
                TimN += 1;
            }
        }
 
  function DDQuitTimEx(timer t) {
   TimTicks[H2ID(t)] = 00;
            PauseTimer(t);
   static if (LIBRARY_TimerUtils)
    ReleaseTimer(t);
            else {
                TimerStack[TimN] = t;
                TimN += 1;
            }
        }
     
        // =================================================================
        //              *** Group Handling ****
        // =================================================================
     
        // -> Load timer for recycling
        function DDLoadGroup() -> group {
            static if (LIBRARY_GroupUtils) { return NewGroup(); }
            else {
                if (GrpN > 0) {
                    GrpN -= 1;
                    return GroupStack[GrpN];
                }
                return CreateGroup();
            }
        }
     
        // -> Recycle group
        function DDRecycleGroup(group g) {
            static if (LIBRARY_GroupUtils) { ReleaseGroup(g); }
            else {
    GroupClear(g);
                GroupStack[GrpN] = g;
                GrpN += 1;
            }
        }
     
        // --------------------------------------------------------
        // -- Quick filter area
  private integer GroupFilterData = 00;
 
        function DDGroupFilterArea(real x, real y, real radius, integer data, code func) {
            group g = DDLoadGroup();
   GroupFilterData = data;
            GroupEnumUnitsInRange(g, x, y, radius, Filter(func));
            DDRecycleGroup(g);
        }
     
        // --------------------------------------------------------
        // -- Quick filter rect
        function DDGroupFilterRect(rect r, integer data, code func) {
            group g = DDLoadGroup();
   GroupFilterData = data;
            GroupEnumUnitsInRect(g, r, Filter(func));
            DDRecycleGroup(g);
        }
     
  function DDGFilterData() -> integer {
   return GroupFilterData;
  }
 
  function DDGFilterDataSet(integer data) {
   GroupFilterData = data;
  }
 
  // --------------------------------------------------------
        // *** Filtrates and fills units in to memory
        function DDGroupFillMemArea(real x, real y, real radius, integer data, code filter) {
   group g = DDLoadGroup();
   boolexpr exp = And(Filter(filter), Filter(function() -> boolean {
    UnitStack[US_N] = GetFilterUnit();
    US_N += 1;
    return false;
   }));
   US_N = 0;
   UnitStack[0] = null;
   UnitStackData = data;
   GroupEnumUnitsInRange(g, x, y, radius, exp);
   DDRecycleGroup(g);
   DestroyBoolExpr(exp);
   exp = null;
  }
 
  function DDGroupFillMemRect(rect r, integer data, code filter) {
   group g = DDLoadGroup();
   boolexpr exp = And(Filter(filter), Filter(function() -> boolean {
    UnitStack[US_N] = GetFilterUnit();
    US_N += 1;
    return false;
   }));
   US_N = 0;
   UnitStack[0] = null;
   UnitStackData = data;
   GroupEnumUnitsInRect(g, r, exp);
   DDRecycleGroup(g);
   DestroyBoolExpr(exp);
   exp = null;
  }
 
  function DDMemUnitN() -> integer { return US_N; }
  function DDMemUnitData() -> integer { return UnitStackData; }
 
  function DDMemUnit(integer index) -> unit {
   if (US_N == 0) return null;
   debug {
    if (index < 0) {
     BJDebugMsg("DDMemUnit: index less than 0");
     index = 0;
    } else if (index >= US_N) {
     BJDebugMsg("DDMemUnit: index greater than units alloc size");
     index = 0;
    }
   }
   return UnitStack[index];
  }
  // --------------------------------------------------------
 
  // --------------------------------------------------------
  // ***
     
        // =================================================================
        //              *** Dummy Handling ****
        // =================================================================
     
        // -> Load dummy for recycling
        function DDLoadDummy() -> unit {
            if (DumN > 0) {
                DumN -= 1;
                PauseUnit(DummyStack[DumN], false);
                return DummyStack[DumN];
            }
            return CreateUnit(Player(0xF), DD_DUMMYCODE, DDMaxX, DDMaxY, 0.);
        }
     
        // *** prepares/setups dummy for spell casting
        function DDLoadSpellDummy(player owner, real x, real y, integer abil, integer abilLevel) -> unit {
            unit dummy = DDLoadDummy();
            SetUnitOwner(dummy, owner, false);
            SetUnitX(dummy, x);
            SetUnitY(dummy, y);
            if (abil != p_null) {
                UnitAddAbility(dummy, abil);
                SetUnitAbilityLevel(dummy, abil, abilLevel);
            }
            return dummy;
        }
     
        // -> Recycle dummy
        function DDRecycleDummy(unit u) {
            PauseUnit(u, true);
            DummyStack[DumN] = u;
            DumN += 1;
        }
     
        // -> Recycle dummy timed
        function DDRecycleDummyTimed(unit u, real secs) {
            DDStartTim(secs, false, New_pUnit(u), function() {
                DDRecycleDummy(p_unit(DDTimData())[0]);
                p_unit(DDTimData()).destroy();
                DDQuitTim();
            });
        }
     
        // *** shares vision for timed amount, usually for dummy casting
        function DDUnitShareVisionTimed(unit u, player toP, real secs) {
            p_integer pi = p_integer.create();
         
            pi[0] = New_pUnit(u);
            pi[1] = GetPlayerId(toP);
            UnitShareVision(u, toP, true);
            DDStartTim(secs, false, pi, function() {
                p_integer pi = DDTimData();
             
                UnitShareVision(p_unit(pi[0])[0], Player(pi[1]), false);
                p_unit(pi[0])[0] = null;
                p_unit(pi[0]).destroy();
                pi.destroy();
                DDQuitTim();
            });
         
        }
 
        // *** Remove ability timed ***
        private struct uratimed {
            private {
                unit u;
                integer abil;
            }
         
            static method create(unit whichUnit, integer id, real time) -> uratimed {
                thistype this = allocate();
             
                u = whichUnit;
                abil = id;
                DDStartTim(time, false, this, function() {
                    thistype this = DDTimData();
                    UnitRemoveAbility(u, abil);
                    DDQuitTim();
                    deallocate();
                });
             
                return 0;
            }
        }
        function DDRemoveAbilityTimed(unit u, integer abil, real secs) { uratimed.create(u, abil, secs); }
     
  function DDSpellDamage(unit u, unit v, real dmg) {
   real life = GetWidgetLife(v);
   real dmgfactor = 1.;
 
   if (IsUnitType(v, UNIT_TYPE_HERO)) {
    if (UnitHasItemOfTypeBJ(v, 'brac'))
     dmgfactor = .5;
    else
     dmgfactor = .75;
   }
 
   if (life > dmg*dmgfactor) {
    SetWidgetLife(v, life-(dmg*dmgfactor));
   } else
    UnitDamageTarget(u, v, 99999., false, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS);
  }
 
  // -------------------------------------------------------------------------------------
  // *** Chills target unit
  private struct chill {
   unit u, dmy;
   real dur;
 
   static chill Data[];
   //static key CHILL_KEY;
  }
 
  function DDUnitChill(player p, unit u, real dur) -> boolean {
   //chill c = DDGet(u, chill.CHILL_KEY);
   chill c = chill.Data[H2ID(u)];
   unit d;
   real rad;
 
 
   if (c == p_null) {
    c = chill.create();
    c.u = u; c.dur = dur;
    chill.Data[H2ID(u)] = c;
    //DDSet(u, chill.CHILL_KEY, c);
 
    d = DDLoadDummy();
    c.dmy = d;
    rad = GetUnitFacing(d) * bj_DEGTORAD;
    SetUnitOwner(d, p, false);
    UnitAddAbility(d, DD_CHILL);
    SetUnitX(d, GetUnitX(u) - 20.*Cos(rad));
    SetUnitY(d, GetUnitY(u) - 20.*Sin(rad));
 
    if (IssueTargetOrder(d, "frostnova", u)) {
     DDStartTim(.1, true, c, function() {
      chill c = DDTimData();
   
      c.dur -= .1;
      if (c.dur <= 0. || GetUnitAbilityLevel(c.u, DD_CHILL_BUFF) == 00) {
       UnitRemoveAbility(c.u, DD_CHILL_BUFF);
       UnitRemoveAbility(c.dmy, DD_CHILL);
       DDRecycleDummy(c.dmy);
       chill.Data[H2ID(c.u)] = p_null;
       //DDSet(c.u, chill.CHILL_KEY, p_null);
       c.u = null;
       c.destroy();
       DDQuitTim();
      }
     });
     return true;
    }
 
    return false;
   }
 
   c.dur = dur;
 
   return true;
  }
 
  // ------------------------------------------------------------------------------------------------
 
  struct fade {
   unit u;
   real trans;
   real rate, e_trans, dur;
 
   static constant real INTERVAL = .1;
 
   static method create(unit u, real dur, real s_trans, real e_trans) -> fade {
    fade this = allocate();
 
    this.u = u;
    this.trans = s_trans;
    this.rate = ((e_trans-s_trans)/dur)*fade.INTERVAL;
    this.e_trans = e_trans;
    this.dur = dur;
 
    return this;
   }
  }
 
  // *** Fades unit over time ***
  public function DDFadeUnit(unit u, integer from_alpha, integer to_alpha, real duration) {
   fade f = fade.create(u,
         duration,
         from_alpha/2.55,
         to_alpha/2.55);
 
   SetUnitVertexColor(u, 255, 255, 255, from_alpha);
   // --- Start thread ---
   DDStartTim(fade.INTERVAL, true, f, function() {
    fade f = DDTimData();
 
    f.trans += f.rate;
    f.dur -= fade.INTERVAL;
    SetUnitVertexColor(f.u, 255, 255, 255, R2I(f.trans*2.55));
 
    if (f.dur < 0.) {
     SetUnitVertexColor(f.u, 255, 255, 255, R2I(f.e_trans*2.55));
     f.u = null;
     f.destroy();
     DDQuitTim();
    }
   });
     
  }
 
  // ------------------------------------------------------------------------------------------------
 
        // Check if unit is invulnerable
        function DDIsUnitInvulnerable(unit u) -> boolean {
            unit d = DDLoadDummy();
            real hp = GetWidgetLife(u);
            boolean flag;
         
            UnitDamageTarget(d, u, 1., true, false, null, null, null);
            flag = GetWidgetLife(u) == hp;
            SetWidgetLife(u, hp);
            DDRecycleDummy(d);
         
            return flag;
        }
     
        // *** check if unit is ward
        function DDIsUnitWard(unit whichUnit) -> boolean {
            return GetUnitDefaultMoveSpeed(whichUnit) == 0.;
        }
 
        // =================================================================
        //              *** Effect Handling ****
        // =================================================================
     
        // -----------------------------------------------
        // *** Define movable effect
        struct ddeffect {
            private {
                effect e;
                real fac; // facing angle in radians
                real effZ; // pitch in radians
                real decay;
    real stepTrans, cTrans, eTrans;
             
                static constant real        EFFECT_DECAY        = 5.;
            }
         
            // =========================================================================================
            // =========================================================================================
            static method create(string mdl, real x, real y, real facRad, real size) -> ddeffect {
                ddeffect this = allocate();
             
                this.e   = AddSpecialEffect(mdl, x, y);
    this.fac  = facRad;
    this.effZ = 0.;
                BlzSetSpecialEffectRoll(this.e, facRad);
    BlzSetSpecialEffectScale(this.e, size);
             
                return this;
            }
 
   static method createZ(string mdl, real x, real y, real z, real facRad, real size) -> ddeffect {
                ddeffect this = allocate();
             
                this.e   = AddSpecialEffect(mdl, x, y);
    this.fac  = facRad;
    this.effZ = z-DDTerrZ(x, y);
                BlzSetSpecialEffectRoll(this.e, facRad);
    BlzSetSpecialEffectScale(this.e, size);
    BlzSetSpecialEffectZ(this.e, z);
             
                return this;
            }
         
            // -----------------
            method destroy() {
                DestroyEffect(this.e);
                this.e = null;
                deallocate();
            }
         
            // *** destroys effect timed
            method destroyx(real decayTime) {
                DDStartTim(decayTime, false, this, function() {
     ddeffect se = DDTimData();
     BlzSetSpecialEffectPosition(se.e, DDMaxX, DDMaxY, 0.);
                    DestroyEffect(se.e);
     se.e = null;
     se.deallocate();
                    DDQuitTim();
                });
            }
            // =========================================================================================
            // =========================================================================================
         
 
         
   method operator Z=(real z)     { BlzSetSpecialEffectZ(this.e, z); }
 
            method operator X() -> real                 { return BlzGetLocalSpecialEffectX(this.e); }
            method operator Y() -> real                 { return BlzGetLocalSpecialEffectY(this.e); }
            method operator Z() -> real                 { return BlzGetLocalSpecialEffectZ(this.e); }
            method operator WZ() -> real                { return DDEffectTerrZ(this.e); }
            method operator Height() -> real            { return this.Z-this.WZ; }
         
            method operator Facing=(real facRad)        { BlzSetSpecialEffectRoll(this.e, facRad); this.fac = facRad; }
            method operator Facing() -> real            { return this.fac; }
 
   method Position(real x, real y)    { BlzSetSpecialEffectPosition(this.e, x, y, this.effZ+this.WZ); }
   method PositionZ(real x, real y, real z) { BlzSetSpecialEffectPosition(this.e, x, y, z); }
   method Animation(animtype at)    { BlzPlaySpecialEffect(this.e, at); }
   method AnimationSpeed(real animSpeed)  { BlzSetSpecialEffectTimeScale(this.e, animSpeed/100.); }
 
   //method operator Pitch=(integer pitch)  { SetUnitAnimationByIndex(u, pitch); }
         
            //method Face(widget w) { Facing = Atan2(GetWidgetY(w)-Y, GetWidgetX(w)-X)*bj_RADTODEG; }
 
   method Fade(real startTransparency, real endTransparency, real duration) {
    this.cTrans = startTransparency;
    this.eTrans = endTransparency;
    this.stepTrans = .1*(endTransparency-startTransparency) / duration;
 
    BlzSetSpecialEffectAlpha(this.e, R2I(startTransparency*2.55));
 
    DDStartTim(.1, true, this, function() {
     ddeffect dde = DDTimData();
  
     dde.cTrans += dde.stepTrans;
     if (dde.stepTrans > 0.)
      if (dde.cTrans >= dde.eTrans) {
       BlzSetSpecialEffectAlpha(dde.e, R2I(dde.eTrans*2.55));
       DDQuitTim();
       return;
      }
     else
      if (dde.cTrans <= dde.eTrans) {
       BlzSetSpecialEffectAlpha(dde.e, R2I(dde.eTrans*2.55));
       DDQuitTim();
       return;
      }
     BlzSetSpecialEffectAlpha(dde.e, R2I(dde.cTrans*2.55));
    });
   }
 
        }
     
  private type timedeffect extends effect[01];
 
  function DDDestroyEffectTimed(effect e, real secs) {
   timedeffect te = timedeffect.create();
   te[00] = e;
   DDStartTim(secs, true, te, function() {
    timedeffect te = DDTimData();
    DestroyEffect(te[00]);
    te.destroy();
    DDQuitTim();
   });
  }
    }
 
 // ----------------------------------------------------------------------------
    // *** Main damage detection function, registers any damage dealt to units ***
    public function DDTriggerRegisterAnyUnitDamaged(trigger t) {
        DmgTrig[NTrig] = t;
        NTrig += 1;
    }
 
    function InitDamageDetection() {
  code c = function() {
   if (TempTrig != null)
    DestroyTrigger(TempTrig);
 
   TempTrig = CreateTrigger();
   TriggerRegisterEnterRectSimple(TempTrig, bj_mapInitialPlayableArea);
   TriggerAddCondition(TempTrig, function() -> boolean {
    integer i;
 
    // *** Check if we need to exec triggers or register an unit ***
    if (GetTriggerEventId() == EVENT_UNIT_DAMAGED) {
     for(i=0; i < NTrig; i+=1)
      if (IsTriggerEnabled(DmgTrig[i]))
       if (TriggerEvaluate(DmgTrig[i]))
        TriggerExecute(DmgTrig[i]);
    }
    else
     // *** Register new unit ***
     TriggerRegisterUnitEvent(GetTriggeringTrigger(),
            GetTriggerUnit(),
            EVENT_UNIT_DAMAGED);
 
    return false;
   });
 
   DDGroupFilterRect(bj_mapInitialPlayableArea, 00, function() -> boolean {
    TriggerRegisterUnitEvent(TempTrig, GetFilterUnit(), EVENT_UNIT_DAMAGED);
    return false;
   });
  };
  trigger t = CreateTrigger();
 
  TriggerAddAction(t, c);
  TriggerExecute(t);
  DestroyTrigger(t);
  TimerStart(CreateTimer(), TRIGGER_REFRESH_RATE, true, c);
  t = null;
    }
 
 // ---------------------------------------------------------------------------------
 
 // *** Main enum dests in range function ***
    public function DDEnumDestsInRange(p_real vec, real radius, boolexpr filter, code pfunc) {
        rect r = Rect(vec[0]-radius, vec[1]-radius, vec[0]+radius, vec[1]+radius);
 
   EnumVec[0] = vec[0];
   EnumVec[1] = vec[1];
   EnumVec[2] = radius;
         
        if (filter != null) filter = And(EnumFilter, filter);
        else filter = EnumFilter;
        EnumDestructablesInRect(r, filter, pfunc);
 
        if (filter != EnumFilter) { DestroyBoolExpr(filter); filter = null; }
  RemoveRect(r);
  r = null;
    }
     
    function InitEnumDests() {
        EnumVec = p_real.create();
        EnumFilter = Filter(function() -> boolean {
            return Pw_2(EnumVec[0]-GetDestructableX(GetFilterDestructable())) + Pw_2(EnumVec[1]-GetDestructableY(GetFilterDestructable())) < Pw_2(EnumVec[2]);
        });
    }
 
 // --------------------------------------------------------------------------------------
 
 // *** checks is destruct tree ***
    public function DDIsDestructableTree(destructable d) -> boolean {
        if (d != null) {
            PauseUnit(TreeChecker, false);
            if (IssueTargetOrder(TreeChecker, "harvest", d)) {
                PauseUnit(TreeChecker, true);
                return true;
            }
            PauseUnit(TreeChecker, true);
        }
        return false;
    }

    function InitDestTreeCheck() {
        TreeChecker = CreateUnit(Player(bj_PLAYER_NEUTRAL_EXTRA), DD_DUMMYCODE, DDMaxX, DDMaxY, 0.);
        UnitAddAbility(TreeChecker, HARVEST_ID);
        PauseUnit(TreeChecker, true);
    }
 
 // --------------------------------------------------------------------------------------
 
 public function DDNewTextTagUnit(unit whichUnit, string text, real dur, real red, real green, real blue, real transparency) {
  CreateTextTagUnitBJ( text, whichUnit, 0., 11.00, red, green, blue, transparency );
  SetTextTagPermanentBJ( bj_lastCreatedTextTag, false );
  SetTextTagVelocityBJ( bj_lastCreatedTextTag, 48.00, 90 );
  SetTextTagFadepointBJ( bj_lastCreatedTextTag, dur-1.25 );
  SetTextTagLifespanBJ( bj_lastCreatedTextTag, dur );
 }
 
 // --------------------------------------------------------------------------------------
 
 struct cameranoisedata {
  player p[12];
  integer n=00;
 }
 
 public function DDCameraSetSourceNoiseForPlayers(real x, real y, real mag, real vel, real maxDist, real duration) {
  integer i;
  real d;
  cameranoisedata cnd = cameranoisedata.create();
 
  for (i=00; i < bj_MAX_PLAYERS; i+=01) {
   if (GetLocalPlayer() == Player(i)) {
    d = SquareRoot( Pw_2(GetCameraTargetPositionX()-x) + Pw_2(GetCameraTargetPositionY()-y) );
    if (d < maxDist) {
     cnd.p[cnd.n] = Player(i);
     CameraSetSourceNoise(mag-(d*(mag/maxDist)), vel-(d*(vel/maxDist)));
     CameraSetTargetNoise(mag-(d*(mag/maxDist)), vel-(d*(vel/maxDist)));
     cnd.n += 01;
    }
   }
  }
 
  DDStartTim(duration, false, cnd, function() {
   cameranoisedata cnd = DDTimData();
 
   while(cnd.n != 00) {
    cnd.n -= 01;
    if (GetLocalPlayer() == cnd.p[cnd.n])
     CameraSetSourceNoise(0., 0.);
     CameraSetTargetNoise(0., 0.);
   }
 
   cnd.destroy();
   DDQuitTim();
  });
 }
 
 // --------------------------------------------------------------------------------------
 
 hashtable GenSndTable = null;
 
    public function DDGenericSound(string file, real vol, real x, real y, real mxDist, real pitch) {
  sound s;
  real d;
  integer i;
  integer snd_n, sh;
     
  // Play sound and shake camera for players within spell cast range
  for (i=00; i < bj_MAX_PLAYERS; i+=01) {
   if (GetLocalPlayer() == Player(i)) {
    d = SquareRoot( Pw_2(GetCameraTargetPositionX()-x) + Pw_2(GetCameraTargetPositionY()-y) );
    if (d < mxDist) {
     sh = StringHash(file);
     snd_n = LoadInteger(GenSndTable, sh, 04);
     s = LoadSoundHandle(GenSndTable, sh, snd_n);
     if (s == null) {
      s = CreateSound(file, false, false, false, 10, 10, "");
      SaveSoundHandle(GenSndTable, sh, snd_n, s);
     } else if (GetSoundIsPlaying(s)) {
      StopSound(s, false, false);
     }
     SetSoundPitch(s, pitch);
     SetSoundVolume(s, R2I((vol-d*(vol/mxDist))*1.27));
     StartSound(s);
     snd_n += 01;
     if (snd_n == 04)
      snd_n = 00;
     SaveInteger(GenSndTable, sh, 04, snd_n);
    }
   }
  }
    }
 
 public function DDGetGameElapsedTime() -> real {
  return TimerGetElapsed(GameElapsedTimer);
 }
 
 public function DDGetRndReal(real min, real max) -> real {
  real rnd = ((max-min)/1000000.)*I2R(RndInt[RndIntReadN]);
  debug if (max > 1000000.)
   DDMsg("ERROR: \"DDGetRndNumber\" - 'max' variable is greater than 1000000!");
  RndIntReadN += 01; if (RndIntReadN == RND_INT_MAX_ARRAY_N) RndIntReadN = 00;
  return min + rnd;
 }
 
 public function DDGetRndInt(integer min, integer max) -> integer {
  return R2I( DDGetRndReal(I2R(min), I2R(max)) );
 }
 
 // ====================================================================
    function onInit() {
  InitDamageDetection();
  InitDestTreeCheck();
  InitEnumDests();
 
        DDMinX = GetRectMinX(bj_mapInitialPlayableArea);
        DDMinY = GetRectMinY(bj_mapInitialPlayableArea);
        DDMaxX = GetRectMaxX(bj_mapInitialPlayableArea);
        DDMaxY = GetRectMaxY(bj_mapInitialPlayableArea);
 
  GenSndTable = InitHashtable();
 
  ErrorSound = CreateSound( "Sound\\Interface\\Error.wav", false, false, false, 10, 10, "" );
  SetSoundParamsFromLabel( ErrorSound, "InterfaceError" );
  SetSoundDuration( ErrorSound, 614 );
  SetSoundVolume(ErrorSound, 127);
 
  GameElapsedTimer = CreateTimer();
  TimerStart(GameElapsedTimer, 10800., false, null);
 
  for(RndIntWriteN=00; RndIntWriteN < RND_INT_MAX_ARRAY_N; RndIntWriteN+=01)
   RndInt[RndIntWriteN] = GetRandomInt(00, 1000000);
 
  RndIntWriteN = 00;
  RndGenForce = CreateForce();
  TrigMouseEvent = CreateTrigger();
  ForForce(bj_FORCE_ALL_PLAYERS, function() {
   if (GetPlayerController(GetEnumPlayer()) == MAP_CONTROL_USER)
    TriggerRegisterPlayerEvent(TrigMouseEvent, GetEnumPlayer(), EVENT_PLAYER_MOUSE_MOVE);
  });
  TriggerAddCondition(TrigMouseEvent, Condition(function() -> boolean {
   real mouseN;
   boolean xFirst = GetRandomInt(00, 01) == 01;
 
   if (!IsPlayerInForce(GetTriggerPlayer(), RndGenForce)) {
    // example: input x = 578.4571496
    //   output rnd n = 4571498
    if (xFirst)
     mouseN = RAbsBJ(BlzGetTriggerPlayerMouseX()) * 100.;
    else
     mouseN = RAbsBJ(BlzGetTriggerPlayerMouseY()) * 100.;
    if (mouseN == 0.)
     return false;
    //mouseN *= 100.;
    RndInt[RndIntWriteN] = R2I((mouseN - I2R(R2I(mouseN))) * 1000.);
    //DDMsg(I2S(RndInt[RndIntWriteN]));
    //RndIntWriteN += 01; if (RndIntWriteN == RND_INT_MAX_ARRAY_N) RndIntWriteN = 00;
 
    if (xFirst)
     mouseN = RAbsBJ(BlzGetTriggerPlayerMouseY()) * 100.;
    else
     mouseN = RAbsBJ(BlzGetTriggerPlayerMouseX()) * 100.;
    RndInt[RndIntWriteN] += R2I((mouseN - I2R(R2I(mouseN))) * 1000.)*1000;
    //DDMsg(I2S(RndInt[RndIntWriteN]));
    RndIntWriteN += 01; if (RndIntWriteN == RND_INT_MAX_ARRAY_N) RndIntWriteN = 00;
    ForceAddPlayer(RndGenForce, GetTriggerPlayer());
   }
 
   if (DDGetGameElapsedTime()-RndElapsedTime > .125) {
    ForceClear(RndGenForce);
    RndElapsedTime = DDGetGameElapsedTime();
   }
 
   return false;
  }));
    }
 
}

//! endzinc




If you have any more questions or suggestions fell free to comment here!
Enjoy!

~Dark Dragon
Contents

DD Universal Pack v5.1c (Map)

Reviews
02:29, 23rd Nov 2008 Dr Super Good: Very good spell pack. All the spells are highly customizable and seem to do their job well. Only problems I noticed are that some spells are not the most efficent. Still I can only recomend using the...

Moderator

M

Moderator

02:29, 23rd Nov 2008
Dr Super Good:
Very good spell pack. All the spells are highly customizable and seem to do their job well. Only problems I noticed are that some spells are not the most efficent. Still I can only recomend using the spells if they are what you are after.

Possiable areas for improvement
- Improve code efficiency.
 
I appreciate your intelligence Blooddancer actually its not a bug but my mistake for allowing it to be casted at barrel. You have my thanks for this one.

Now Its updated and cant be cast on barrel (destructable) as ofc i used GetSpellTargetUnit(), GetUnitX, Y ... and ofc it did not work.

Thanks again!

About part in custom models, I know that you people don't like it for some reason 'size' but i think its nice to give people idea on which model or hero can spells be used on.
 
About part in custom models, I know that you people don't like it for some reason 'size' but i think its nice to give people idea on which model or hero can spells be used on.

Its no just the downbload size
its also the size of all Spells and datas of Hive atall
Because its just useless to have one model 1000 times in different Spells and model section

The Spells look nice , but the blademasters Spell looks really strange and not intentioned when casted from a very short range

The first time i casted Dark Torture one Sword was not removed and stayed forever

All in all they look nice but its such an huuuge code , i was too lazy to check everything but i can imagine that some things are not really necessary

Ill give you a [4/5] for this
 
Level 17
Joined
Sep 8, 2007
Messages
994
Well, I will not rate in my standard rating style this time because the code is too long...

omg xD nearly 3400 lines used totally for 3 spells, sooooooooo many globals and using a library for a spell (?)...
I am not very sure but you surely have planned that. I usually only use libraries for systems and scopes for spells.
Well, the spell performace rockz and I give a 10/5 for that, ideas are great. The coding seems to be leakless, perfect but also clearless. I can't figure out to configure it xD Well, 5/5 from me.
 
Level 22
Joined
Jun 24, 2008
Messages
3,050
I know its not a real bug, but its more like an error, cause you made the spell to target 'objects' and not 'units'. But if you somehow, did not remove this, then most people would say that i was a 'bugg' therefor: Bug :D

Also: Hell'a lot of lines. But also pretty neat spells. You should work on:
  • Not importing models.
  • Less lines

Regards~
TheBlooddancer
 
o_O alot of lines :p the spellpack made my comp crash about 3 min into testing for sum reason... My computer has never crashed beafore...

Ok lets see, for some reason my pc starts to lag like hell when using vjass test map option, dont know why. So please test the spells by default starting your Warcraft III.
Ty!

Well, I will not rate in my standard rating style this time because the code is too long...

omg xD nearly 3400 lines used totally for 3 spells, sooooooooo many globals and using a library for a spell (?)...
I am not very sure but you surely have planned that. I usually only use libraries for systems and scopes for spells.
Well, the spell performace rockz and I give a 10/5 for that, ideas are great. The coding seems to be leakless, perfect but also clearless. I can't figure out to configure it xD Well, 5/5 from me.

I guess ill just have to wait for you to find time rating this in your nice rate system.
About globals lets see, I made a lots of em to simple edit spell stile, and I am not using any objects storage systems so I need direct one hell of a variables. But dont worry they do not pass the limit of 8191 so they are fast. And you can cast this spells a lots of time in same time. Game Cache limit if 255 variables at same time, which is lol for me.

Hmm scopes can they do requires and initializer anyway somehow i love keyword library much more I guess it does not cause any trouble to you.
Ty for comment.

Its no just the downbload size
its also the size of all Spells and datas of Hive atall
Because its just useless to have one model 1000 times in different Spells and model section

The Spells look nice , but the blademasters Spell looks really strange and not intentioned when casted from a very short range

The first time i casted Dark Torture one Sword was not removed and stayed forever

All in all they look nice but its such an huuuge code , i was too lazy to check everything but i can imagine that some things are not really necessary

Ill give you a [4/5] for this

Thanks for rating. Ok if you really say that you want that model removed or causes you trouble ill remove it.

Yep blademaster spell is something special as it damages units which are exactly at sword position i did one hell of a trigonometry out there, but anyway at short range it can damage only once and this once it must be at sword position. Last slash it 100% to be target.

Ok about that swords stay this has to do with collision but ill check this right away.

Thank you for your comment!

I know its not a real bug, but its more like an error, cause you made the spell to target 'objects' and not 'units'. But if you somehow, did not remove this, then most people would say that i was a 'bugg' therefor: Bug :D

Also: Hell'a lot of lines. But also pretty neat spells. You should work on:
  • Not importing models.
  • Less lines

Regards~
TheBlooddancer

Yes ofc ty. About models lol if someone really tells me remove it now then I will.
About less lines. Its because i want to make inline functions actually not make functions but when i got idea of Dark Torture i said like hell more then 2000 lines for one spell is kind killing. But you know this spells are so good made that even if you cast then 5x times at same time its gonna be a little slower then 1x times. Every spell has one global timer this timer lives only when there are TimesOfCast > 0 thats how it is.

Thank you for comment!
 
Last edited:
About models lol if someone really tells me remove it now then I will.

Effects or Icons are not necessary but imo its Ok. Sometimes there is just no matching Icon or Spell look crap with other models (e.g. these swords)
I didnt look if you did but you should credit the creators and make i hint that Mapper which use your Spell should credit them too

But I think a big model for a hero is really not needed
 
I would like you to remove the custom models, and see if you can get same result. If, then edit this upload.

Oh, yea, and you might wanna merge your double post before Rui see's you.

Double post? Didn't I click on update?:confused:

Effects or Icons are not necessary but imo its Ok. Sometimes there is just no matching Icon or Spell look crap with other models (e.g. these swords)
I didnt look if you did but you should credit the creators and make i hint that Mapper which use your Spell should credit them too

But I think a big model for a hero is really not needed


Both of you i removed the so irritating model :hohum:
Well anyway now you happy :wink:

The first time i casted Dark Torture one Sword was not removed and stayed forever

Thank you for finding about this and telling me out. Its fixed + added swords pathing type to NONE from fly so swords will always move at same height even on terrain. Beautiful to see!!! :thumbs_up:

Once more thank you for comments and have a nice day!
 
Yap the boolexpr i use is only (object exist during spell is cast (only one)), when spell ends the object is not needed to be in game anymore so its destroyed. It does returns same object but its object so when spell ends there is no need to leave that object live. In other way some people just make one object which will live always so they dont destroy it, but i am making object exist only during the spell (one of object per spell). As less object in map the less chance to for lag is possible because the object cause lag in maps. Well that's like location, it always returns same location but we will remove it to cause no leak. Even if we could move location whole the time but we remove it coz there would be one hell of a objects in map and when playing on Battle.net with a lot of players hell game would lag hard. Thats why object methodes (functions) are made.

Once more thank you for comment and approving!
Best regards!
 
Level 10
Joined
Apr 13, 2005
Messages
630
I like to say this spell is something brand new to warcraft. The lightning spell thought aint much new since there are tons but the sword spell blows my mind. I did find a bug if this is meant or not. If you do blademaster ability and it hits a tree or rock it will stop it.
My rating is 5/5 +rep
 
Level 1
Joined
Feb 1, 2009
Messages
3
Bug

just letting u know tht sometimes when using dark torture the two swords farthest down dont move and arnt deleted they just stay in mid air
 
just letting u know tht sometimes when using dark torture the two swords farthest down dont move and arnt deleted they just stay in mid air

thanks for comment, unfortunently i am not sure how stuff happend since i already fixed that and yes it was the same bug but then fixed it and casted spell a lot of times to make sure it works it was fixed but now well again i tried and it works really not sure how that happend to you but if you find time to explain exactly how that happend to you and so on... i would be glade.

In fact you don't thanks anyway for letting me know if i find why ill fix it!
 
Level 19
Joined
Aug 24, 2007
Messages
2,888
Yes imports make spells cool
actually people mostly get impressed by special effects not what spell does ("mostly" not all the time)

Anyway I liked them (didnt check coding though and I dont care about coding) wont rate though (its already 5 lol) I was gonna say 4 but didnt wanna reduce overall rating
 
k thanks and i was really wondering why nobody comments on how spells are coded since they are long to read i guess :D

well i started my vjass knowledge on this spell pack first spell was Slash Strike which is the fastest i guess but i coded directly using globals... almost no custom functions at last this which are constants heh... and so on i guess that difference between each spell can be clearly seen now!

once again thanks for comment and +rep
~Dark Dragon
 
I was going to say that the warning message seemed a bit unnecessary, but after reading down i see why it's there.
But back to topic:
I loved these spells and found two small things.
There was an instince where i casted the dark torture spell and there were 2 units towards the left side of the spell effect, where there were 2 swords. The units were not close enough to be hit by the spell, but for some reason the swords just stayed there. They didnt make a sound, they just spawned and stayed. Also, a lot of times the spell cast was wasted because the range of it initiated attack and the units generally avoided the effects of the spell.
Also, the frozen orb spell should create more frost bolts, and maybe a better model for the frost bolts. The ice shard didn't seem to really fit.

In the positive notes:
-The spells had super amazing tooltips
-The idea for using the blood mage skin was great, and I think that the "Giving ideas for what hero the spell should be used on" idea should be implemented in every spell map. Think about it, it's just like renaming the proper name of a hero. That has nothing to do with the spell, but it usually doesn't hurt a thing.
-Almost every spell worked perfectly
-The spells were all versatile and useful

I would rate this a 5/5
Good... Great work.
 
Level 12
Joined
Jan 6, 2009
Messages
848
hey, i think you misunderstood me there. The spells aren't bad! It's just the ideas that are a little boring... except that blademaster thingie:wink: and frost eruption:grin: those are great!
 
Level 2
Joined
Mar 5, 2009
Messages
5
Visually very stunning i liked it alot

Future Improvents (Optional):

Like Dynasti said i also tryed to test the map also crashed for me 3-4 minutes in so if possible please find out the problem and correct it

Possibly reduce the amount of triggers you use to make it run more smootly (Less Lag/Leaks)

Not really necessary to have custom icons just wastes space i think

i give it a 4.2/5
 
Level 1
Joined
Mar 14, 2009
Messages
2
Sorry to ask but i cant seem to be able to import the triggers, i have tried all from copying to .... really all .... any help here?

And great spells.
(didnt rate tough)
 
well thanks for comment i found out some things and i think that Electric Field once caused little lagg in game so i think thats it or actially slash strike as for some reason it sometimes buggs so i am sure its slash strike which buggs the map and well i hope to find out why slash strike does that. Reduce triggers GUI or Jass way if Jass then no, in this spells each trigger exists per cast and because of that its fast when there are a lot of casts at same time. Less lag well as i said must find why slash strike buggs it, leaks if there is a single one plz tell me, i am 100% sure i removed all including null leak. Icons well its true but my spell pack is created to use as much custom stuff as possible...

4.2/5 is fine its true that i must find why slash strike buggs stuff out so yeah one more thanks for comment!
 
Level 1
Joined
Mar 14, 2009
Messages
2
Still i cant get to get theese spells into my map ....

BUT i found a bug when you use Slash Strike in close combat blademaster just keeps flying straight ahead ... untill he hits the end of map where hes just standing.
 
ty for your comment DrHaK!

yes it seems this map just has handle stack corruption and that is the only reason why spell could do that.

no worry i allready fixed that and now i just need to get some idea to make some spell and upload fixed map.

About importhing spells in your map did you read comments in my spells there it is explained how to install them.

if you still need help you can ask here!
~Dark Dragon
 
Your Slash Strike still bugs sometimes.
when casting the caster moves to his right and begins to move
->I casted it while there were doodads on the casters right side so he was blocked and his start position was nearly his end position ( ~ a 50 distance away). Then while moving to the target the caster didnt turn arround , he just moved straight and never stopped till he was outside of the map. i think that was not planned

Edit : added replay , may help
 

Attachments

  • LastReplay.w3g
    11.4 KB · Views: 188
Hi -JonNny and thanks for posting bug!

actually i am currently working hard on v3 and its supposed to be out soon but still cant say the exact date. that bug you posted might happen coz my map is corrupted with so called 'handle stack corruption' it replaces variables and makes map to stop working how it is supposed to... its because i used bug returns thats what make problems with generating new variables...

however i already fixed all of that but i cant upload v3 with nothing new right? xD
thanks again +rep!
~Dark Dragon
 
Top