• 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.

Spell - Freezing Field 2.1b

DotA - Freezing Field Remasterd Contains:
Spell - Freezing Field
Item - Scepter


Summons multi explosions around the Jaina damaging enemys and slowing them for x seconds.




Version 1.1 - Heavy reduced code and no lag when casting anymore.

Version 1.2 - Reduced code again and lag completly removed.

Version 1.3 - Now casters offset is also cleared ( caster point stored and cleared )

Version 1.4 - One of greater spells in world, allowing jass programers to use jass code and GUI programers to use GUI. Still there is 2x Jass triggers one for jass-ers, one for GUI-ers (Jass Advanced) - wich contains 2x triggers one jass and other GUI vars setup for jass trigger. However there is the GUI 4x trigger which I dont suggest to use.
Ver 1.4 adds 2x jass triggers 1x GUI trigger which allows GUI-ers simply edit and custom grafics in both jass allowed SINGLE GUI NOT but GUI jass yes. Very simple edit grafics to for GUI-ers and jass-ers. Maded in Jass Craft editor.

Version 1.4b - Reduced code and used more natives.

Version 1.5 - This is final update, changes are: Code fully optimized and MUI for 2x triggers. (GUI and Jass) and (Jass), single GUI does not need updates as no one will use it, because the GUI trigger which setups Jass one will to very high optimizations in your map.

Version 1.6 - Some fixes in GUI and JASS + jass fixes first lag cast.

Version 1.7 - Spell now contains GUI, GUI/Jass, Jass, vJass (codes) well as you can see its arranged by how good it is first is the worsest and last is the best. Well we are talking about leaks and performances so pick what you want, but note that every code is different, not all codes create custom graphics and some create in different way. I must say that all other then final vJass code are using constant explosions which means they will be create all around you 100%, since we can't know how randomize will work. However i decided to improve random generator with my own simple one and seed. The vJass code does not leak even a single leak and is the fastest, most readable and best documented. I highly suggest you to pick vJass as you can fully customize Freezing Field spell there and you don't need to copy any globals and such... Just go to Freezing Field vJass code and start reading from top until it says don't edit here if you don't know jass.
All installation documentation is in that trigger so you need to know english to understand how easy you can modify this spell. The vJass uses all dynamic objects for spell and as said does not leak anything. However if you still want some other code like you don't understand vJass and you want Jass then pick that, or maybe you just want GUI. As fare as I remember GUI is not MPI, nor did i check it out now. Well you will get the idea of how GUI is done so if you want make it for yourself MUI coz I am not GUI programmer any more and it just blocks my mind to make things how they should be. I would really update GUI but its pointless as even by using GUI your map will leak so as i know how bad GUI is not to say 'SLOW' i just can't code back in it. Ofc i like GUI coz all my programming knowledge started on GUI.

Version 1.7b - Just made dummys unselectable!
Credits goes to N8-11_GER for telling me about this

Version 1.8 - Optimized script, improved performances and made it 1.24+ compatible!

Version 2.0 - Freezing Field Remasterd
- Totally recoded in zinc
- Can be modified a lot in setup part of trigger
- Now uses mini library

Version 2.1 - Recoded in Warcraft 3 v1.30, no longer requires JNGP

Version 2.1b - Fixed desync sound bug




Have fun, this is one of my favorite spells and I hope you enjoy as much as I do.
This is an old Freezing Field DotA spell... Not new one!


=================================

Credits:
=================================


IceFrog - For most idea of spell and Scepter
PurplePoot - For teaching me most of the jass and approving this spell
Hanky - For teaching me as well some things i did not understand like boolexpr null leak
Hive - For hosting my project
Blizzard - For making game


===============================
FAQ
===============================


Q: Will you make the GUI leakless and good as vJass, I don't understand vJass?

A: I am sorry but no, even if you make spells in GUI you must use Custom Script to clear 70% of leaks. So fully leakless in GUI is not possible as well as in Jass but jass can handle 94% leaks fixed. As well i must say I am bad in GUI coz it just blocks my imagination to put in code...

Q: You said vJass is fully customizable but i want to change damage amount and can't find that variables, as well there is variable called ExplosionDur[Level] and even if i change that my caster can move after 3.5 seconds, so how do i fix that?

A: That part goes for Object Editor the damage, slow duration and all that is done in Object Editor, find Freezing Field Damage which is dummy ability and set it up to your stile. About channel time you must change value in Object Editor Freezing Field ability and find Channel Duration then change it to your value in Trigger Editor

Q: Do i need to give credits to you?

A: No, the most idea belongs to IceFrog so i don't ask for credits, i just made it because its one of my favorite spells.

Q: Many spells casted at same time causes my computer to lag, does this spell lag?

A: It depends on your computer, but it should not lag for about 3 casts at same time. 4'th cast might cause only a little visible lag. Still it depends on your PC. However i can say that its coded well so it should not lag for you, but test it on your own.

Q: How can i install this spell? when i open my map it just does not want to past it

A: That is because you must not close my map when copy and pasting data. Just use File -> Open Map so your data does not get erased.


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

JASS:
[/B]
//TESH.scrollpos=102
//TESH.alwaysfold=0
// *****************************************************************************
// *      Spell: Freezing Field
// *      -> By: Dark Dragon
// *
// *
// *
// *      --- Installation ---
// *
// * - 1. Copy this trigger and DD Library if not already
// * - 2. Export and import Aghanims Scepter icon if you want
// * - 3. Copy and paste abilities Freezing Field Damage (Dummy), Freezing Field and its Updated (if you want) version to your map
// * - 4. Start editing below until it says "Custom spell code"
// * - 5. Enjoy!
// *****************************************************************************


// =====================================================================
// Freezing Field library
//
//! zinc
library FreezingField requires DDLib
{

 // **********************************************************
 // ---    Editable Spell Globals
 // **********************************************************
 
 // This is the rawcode of the spell frezzing field
 // Default: 'FFld'
 constant  integer    FF_RAWCODE       = 'FFld';
 
 // This is the rawcode of the spell frezzing field upgraded
 // Default: 'FFdu'
 constant  integer    FFU_RAWCODE      = 'FFdu';
 
 // This is the dummy ability frost nova
 // Default: 'FFDg'
 constant  integer    DFN_RAWCODE      = 'FFDg';
 
 // This is the casters channel effect model
 // Default: "Abilities\\Spells\\Items\\TomeOfRetraining\\TomeOfRetrainingCaster.mdl"
 constant  string     CEFF_MODEL       = "Abilities\\Spells\\Items\\TomeOfRetraining\\TomeOfRetrainingCaster.mdl";
 
 // This is the path to sound file which will be played when spell is cast
 // Default: "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget1.wav"
 constant  string     GLACIER_SOUND_FILE_PATH   = "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget1.wav";
 // Sound volume in percentage
 // Default: 100%
 constant  real     GLACIER_SOUND_VOLUME   = 100.;
 // Default 0.5
 constant  real     GLACIER_SOUND_PITCH    = 0.5;
 // Default 3500.
 constant  real     GLACIER_SOUND_MAX_DISTANCE   = 3500.;
 
 // This is offset from caster to cause nova damage, meaning to not create explosions on position of caster
 // Default: 50.
 constant  real    NOVA_OFFSET      = 50.;
 
 // Area of effect of nova, radius
 // Default: 70.
 constant  real    NOVA_AREA      = 70.;
    
    // Area of effect of the spell, radius, AoE can only be certain numbers that follow the formula:
    // NOVA_OFFSET + NOVA_AREA * n, where n is integer number
 // Default: 470. AoE / n is 6
 constant  real    FREEZING_FIELD_AREA    = NOVA_OFFSET + NOVA_AREA * 6.;
 
 // Explosions per second
 // Default: 12
 constant  integer    EXPLOSIONS_PER_SECOND   = 12;
 
 // Use ice fall graphics, eye candy, but uses more system resources
 // Default: true
 constant boolean    ICE_FALL_USE     = true;
 
 // Model file used for graphic display
 // Default: "Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathMissile.mdl"
 constant string    ICE_FALL_MODEL     = "Abilities\\Spells\\Undead\\FreezingBreath\\FreezingBreathMissile.mdl";
 
 // Size of ice fall block (model)
 // Default: 0.66
 constant real    ICE_FALL_SCALE     = 0.66;
 
 // Ice fall offset from blast point
 // Default: 340., 400.
 constant real    ICE_FALL_MIN_OFFSET    = 340.;
 constant real    ICE_FALL_MAX_OFFSET    = 400.;
 
 // Ice fall initial height and gravity acceleration
 // Default: 1200., 3600.
 constant real    ICE_FALL_HEIGHT     = 1200.;
 constant real    ICE_FALL_ACCELERATION   = 3600.;
 
 // Ice fall angle in degrees
 // Default: -20., 50.
 constant real    ICE_FALL_MIN_ANGLE    = -20.;
 constant real    ICE_FALL_MAX_ANGLE    = 50.;
 
 // Use custom terrain type
 // Default: true
 constant boolean    DO_PAINT_FIELD     = true;
 
 // Terrain type id
 // Default: 'Iice'
 constant integer    FIELD_TYPE      = 'Iice';
 
 // Terrain offset duration after spell end cast
 // Default: 3.
 constant real    PAINT_FIELD_OFFSET_DUR   = 3.;
 
 
 // =========================================================================
 // ----               ----
 //      *** Custom spell code ***
 // ----               ----
 // =========================================================================
 
 // Default: auto
    boolean     FreezingFieldChanneling[];
 
 
 // ---------------------------------------------
 // * Main data for storing terrain type, and altering it
 // ---------------------------------------------
 struct altfield {
  private {
   integer typ[64], var[64];
   boolean blighted[64];
   real X[64], Y[64];
   integer n=0;
   
   unit bc[64];
   integer bca[64];
   integer bcn;
   
   static  constant   integer   BLIGHT_ABIL_LARGE     = 'Abgl';
   static  constant   integer   BLIGHT_ABIL_SMALL     = 'Abgs';
   static  constant   real   BLIGHT_ABIL_RADIUS     = 960.;
   
  }
  
  private method RemoveBlightAbilArea(real x, real y, boolean remove) {
   if (remove) {
    bcn = 0;
    DDGroupFillMemArea(x, y, BLIGHT_ABIL_RADIUS+FREEZING_FIELD_AREA, this, function() -> boolean {
     thistype this = DDMemUnitData();
     if (GetUnitAbilityLevel(GetFilterUnit(), BLIGHT_ABIL_LARGE) > 0) {
      bc[bcn] = GetFilterUnit();
      bca[bcn] = BLIGHT_ABIL_LARGE;
      UnitRemoveAbility(bc[bcn], BLIGHT_ABIL_LARGE);
      bcn += 1;
     } else if (GetUnitAbilityLevel(GetFilterUnit(), BLIGHT_ABIL_SMALL) > 0) {
      bc[bcn] = GetFilterUnit();
      bca[bcn] = BLIGHT_ABIL_SMALL;
      UnitRemoveAbility(bc[bcn], BLIGHT_ABIL_SMALL);
      bcn += 1;
     }
     return false;
    });
   }
   
   else {
    while(bcn > 0) {
     bcn -= 1;
     if (GetUnitAbilityLevel(bc[bcn], bca[bcn]) == 0)
      UnitAddAbility(bc[bcn], bca[bcn]);
     
    }
   }
  }
  
  
  method FreezeField(real x, real y) {
   real w = -FREEZING_FIELD_AREA, h, maxh;
   //n = 0;
   
   RemoveBlightAbilArea(x, y, true);
   
   while(w <= FREEZING_FIELD_AREA) {
    maxh = SquareRoot(Pw_2(FREEZING_FIELD_AREA) - Pw_2(w));
    h = -maxh;
    
    do {
     if (GetTerrainType(x+w, y+h) != FIELD_TYPE) {
      X[n] = x+w; Y[n] = y+h;
      typ[n] = GetTerrainType(X[n], Y[n]);
      var[n] = GetTerrainVariance(X[n], Y[n]);
      
      blighted[n] = IsPointBlighted(X[n], Y[n]);
      if (blighted[n])
       SetBlightPoint(Player(0xF), X[n], Y[n], false);
      
      SetTerrainType(X[n], Y[n], FIELD_TYPE, -1, 1, 0);
      n += 1;
     }
     h += bj_CELLWIDTH;
    } while(h <= maxh);
    
    w += bj_CELLWIDTH;
   }
  }
  
  method UnfreezeField() {
   if (n > 0) {
    while(n >= 0) {
     n -= 1;
     SetTerrainType(X[n], Y[n], typ[n], var[n], 1, 0);
     if (blighted[n])
      SetBlightPoint(Player(0), X[n], Y[n], true);
    }
   }
   RemoveBlightAbilArea(0., 0., false);
  }
 }
 
 // -----------------------------------------------------
 // *** primary spell data ***
 // -----------------------------------------------------
 struct ffdata {
  unit caster;
  player owner;
  integer rnd[EXPLOSIONS_PER_SECOND], rnd_n;
  integer lvl;
  altfield af;
  
  private {
   static  real  OX[], OY[];
   static integer  ON = 0;
   static  location BlastLoc = null;
  }
  
  static method create(unit c, integer l) -> ffdata {
   ffdata this = allocate();
   
   caster   = c;
   owner  = GetOwningPlayer(c);
   rnd_n  = 0;
   lvl   = l;
   static if (DO_PAINT_FIELD) {
    af = altfield.create();
    af.FreezeField(GetUnitX(caster), GetUnitY(caster));
   }
   
   return this;
  }
  
  method destroy() {
   static if (DO_PAINT_FIELD) {
    DDStartTim(PAINT_FIELD_OFFSET_DUR, false, af, function() {
     altfield af = DDTimData();
     af.UnfreezeField();
     af.destroy();
     DDQuitTim();
    });
   }
   deallocate();
  }
  
  // *** This is called every second ***
  method TryResetRndN(integer tick) {
   if (ModuloInteger(tick, EXPLOSIONS_PER_SECOND) == EXPLOSIONS_PER_SECOND-01)
    rnd_n = 0;
  }
  
  // *** returns random n, that is not used ***
  // *** every second this is reseted to 0 ***
  private method GetRndN() -> integer {
   integer n, i;
   boolean flag;
   
   do {
    n = DDGetRndInt(0, ON-1);
    flag = false;
    for(i=0; i < rnd_n; i+=1)
     if (rnd[i] == n) {
      flag = true;
      break;
     }
   } while(flag);
   
   rnd[rnd_n] = n;
   rnd_n += 1;
   
   return n;
  }
  
  // *** Gets us the blast location X, Y ***
  method GetRndLoc() -> location {
   integer n = GetRndN();
   MoveLocation(BlastLoc, GetUnitX(caster) + OX[n], GetUnitY(caster) + OY[n]);
   return BlastLoc;
  }
  
  // --------------------------------------------
  // *** Init static globals ***
  static method onInit() {
   real SAFE_SHIFT = 5.;
   real INIT_RADIUS = NOVA_AREA+NOVA_OFFSET;
   integer MAX_I = R2I( ((FREEZING_FIELD_AREA-INIT_RADIUS-NOVA_AREA+SAFE_SHIFT) / (2.*NOVA_AREA)) ), MAX_J;
   
   integer i, j;
   real r;
   
   BlastLoc = Location(0., 0.);
   
   // *** Loop through radius ***
   for(i=0; i <= MAX_I; i+=1) {
    // Get current radius and fill circumference with nova circles
    r = INIT_RADIUS + (i*2.*NOVA_AREA);
    MAX_J = R2I(bj_PI / Atan(NOVA_AREA/r));
    for(j=0; j < MAX_J; j+=1) {
     // *** Loop through angle, and store points ***
     OX[ON] = r * Cos(j*(2.*bj_PI/MAX_J));
     OY[ON] = r * Sin(j*(2.*bj_PI/MAX_J));
     ON += 1;
    }
   }
   //BJDebugMsg(I2S(ON));
  }
  
 }
 
 
 // -------------------------------------------------------
 // *** Ice fall graphic struct
 // -------------------------------------------------------
 public struct icefall {
  private {
   ddeffect dde;
   //real x, y, z;
   real ox, oy, wz;
   player p;
   integer l;
  }
  
  // -----------------------------------
  // *** Constructor
  static method create(player owner, real x, real y, integer lvl) -> icefall {
   icefall  this    = allocate();
   real   xy_shift   = DDGetRndReal(ICE_FALL_MIN_OFFSET, ICE_FALL_MAX_OFFSET);
   real   alpha    = GetRandomReal(ICE_FALL_MIN_ANGLE, ICE_FALL_MAX_ANGLE)*bj_DEGTORAD;
   real  t     = SquareRoot(2.*ICE_FALL_HEIGHT/ICE_FALL_ACCELERATION);
   real   dx     = Cos(alpha),
      dy     = Sin(alpha);
   
   wz = DDTerrZ(x, y);
   dde = ddeffect.createZ(ICE_FALL_MODEL, x + xy_shift * dx, y + xy_shift * dy, wz + ICE_FALL_HEIGHT, 1.5*bj_PI, ICE_FALL_SCALE);
   ox = DD_INTERVAL*-dx*xy_shift/t;
   oy = DD_INTERVAL*-dy*xy_shift/t;
   p = owner;
   l = lvl;
   
   return this;
  }
  
  static method FrostNovaExplosion(player owner, real x, real y, integer lvl) {
   unit dummy = DDLoadSpellDummy(owner, x, y, DFN_RAWCODE, lvl);
   UnitRemoveAbility(dummy, 'Aloc');
   IssueTargetOrder(dummy, "frostnova", dummy);
   DDStartTim(1., false, New_pUnit(dummy), function() {
    p_unit pd = DDTimData();
    SetWidgetLife(pd[0], GetUnitState(pd[0], UNIT_STATE_MAX_LIFE));
    UnitAddAbility(pd[0], 'Aloc');
    UnitRemoveAbility(pd[0], DFN_RAWCODE);
    DDRecycleDummy(pd[0]);
    pd.destroy();
    DDQuitTim();
   });
  }
  
  // -----------------------------------
  // *** Run motion, auto destroy
  method InitMotion() {
   DDStartTim(DD_INTERVAL, true, this, function() {
    icefall this = DDTimData();
    integer tick = DDTimTick();
    
    // *** Motion of ice blocks ***
    dde.PositionZ(dde.X + ox, dde.Y + oy, wz + ICE_FALL_HEIGHT - (.5*ICE_FALL_ACCELERATION*Pw_2(tick*DD_INTERVAL)));
    /*xe.Y += oy;
    xe.Z = ICE_FALL_HEIGHT - (.5*ICE_FALL_ACCELERATION*Pw_2(tick*DD_INTERVAL));*/
    
    // *** Impact?
    if (dde.Z < 10.) {
     FrostNovaExplosion(p, dde.X, dde.Y, l);
     dde.destroy();
     destroy();
     DDQuitTim();
    }
   });
  }
 }
 
 
 // =========================================================================
 //
 //      *** Init spell Freezing Field ***
 //
 // =========================================================================

 function onInit() {
  trigger t = CreateTrigger();
  TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT);
  TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_ENDCAST);
  TriggerAddCondition(t, Condition(function() -> boolean {
   ffdata d;
   integer lvl;
   unit u;
   
   // ------------------------------------------------
   // Primary condition
   // ------------------------------------------------
   if (GetSpellAbilityId() != FF_RAWCODE && GetSpellAbilityId() != FFU_RAWCODE)
    return false;
   
   u = GetTriggerUnit();
   
   // ------------------------------------------------
   // Check if spell is done
   // ------------------------------------------------
   if (GetTriggerEventId() == EVENT_PLAYER_UNIT_SPELL_ENDCAST) {
    // *** End spell ***
    FreezingFieldChanneling[H2ID(u)] = false;
    return false;
   }
   
   // ------------------------------------------------
   // New instance initialize
   // ------------------------------------------------
   if (GetSpellAbilityId() == FF_RAWCODE)
    lvl = GetUnitAbilityLevel(u, FF_RAWCODE);
   else
    lvl = GetUnitAbilityLevel(u, FFU_RAWCODE) + 01;
   
   d = ffdata.create(u, lvl);
   
   // *** Play sound ***
   DDGenericSound(GLACIER_SOUND_FILE_PATH, GLACIER_SOUND_VOLUME, GetWidgetX(u), GetWidgetY(u), GLACIER_SOUND_MAX_DISTANCE, GLACIER_SOUND_PITCH);
   
   // *** Is casting = true
   FreezingFieldChanneling[H2ID(u)] = true;
   DDStartTimInst(1./EXPLOSIONS_PER_SECOND, true, d, function() {
    ffdata d = DDTimData();
    integer tick = DDTimTick();
    location l;
    
    // *** Quit spell ***
    if (!FreezingFieldChanneling[H2ID(d.caster)]) {
     d.destroy();
     DDQuitTim();
     return;
    }
    
    // *** Load caster effect ***
    if (ModuloInteger(tick, 02*EXPLOSIONS_PER_SECOND) == 01)     
     DestroyEffect( AddSpecialEffectTarget(CEFF_MODEL, d.caster, "origin") );
    
    l = d.GetRndLoc();
    
    // *** Create explosion ***
    static if (ICE_FALL_USE)
      // static location
     icefall.create(d.owner, GetLocationX(l), GetLocationY(l), d.lvl).InitMotion();
    else
     icefall.FrostNovaExplosion(d.owner, GetLocationX(l), GetLocationY(l), d.lvl);
     
    // *** Every second all possible locs are reseted
    d.TryResetRndN(tick);
   });
   
   
   // ------------------------------------------------
   //
   // *** End trigger condition ***
   //
   u = null;
   return false;
   // ------------------------------------------------
  }));
  
  
  // ----------------------------
  // *** Load sound ***
  /*
  GlacierExplode = CreateSound(GLACIER_SOUND, false, true, true, 10, 10, "DefaultEAXON");
  SetSoundParamsFromLabel(GlacierExplode, "FrostNova");
  SetSoundPitch(GlacierExplode, 0.5);
  SetSoundVolume(GlacierExplode, 127);
  */
 }
}
//! endzinc

// ============================================================================================
// Change me from /* to // and then back to /* after saving and reopening the map
    // |
    // ˇ
      /*
      
// Credits: PurgeandFire for lua tutorial
//! externalblock extension=lua ObjectMerger $FILENAME$
     //! i -- ===================================================
     
     //! i FREEZING_FIELD_DAMAGE_ID             = "FFDg"
     //! i FREEZING_FIELD_ABIL_ID               = "FFld"
     //! i FREEZING_FIELD_IMPROVED_ABIL_ID      = "FFdu" -- Set this value to "nil" if not using upgrader
  //! i CHAIN_FROST_ABIL_ID     = "CFro"
  //! i CHAIN_FROST_IMPROVED_ABIL_ID   = "CFru" -- Set this value to "nil" if not using upgrader or if not using chain frost spell
  //! i AGHANIM_SCEPTER_ABIL_ID    = "Aghs"
    
     //! i -- ===================================================
    
     //! i setobjecttype("abilities")
     //! i createobject("AUfn", FREEZING_FIELD_DAMAGE_ID)
     //! i makechange(current,"anam", "Freezing Field Damage")
     //! i makechange(current,"alev", "4")
     //! i makechange(current,"aher", false)
     //! i makechange(current,"arac", "nightelf")
     
     //! i local i = 0
     //! i for i=1, 4 do
        //! i local si = tostring(i)
        //! i makechange(current,"atar",si,"Enemy,Ground,Organic,Self")
        //! i makechange(current,"Ufn2",si,"0.")
        //! i makechange(current,"aare",si,"160.")
        //! i makechange(current,"ahdu",si,"4.")
        //! i makechange(current,"adur",si,"6.")
        //! i makechange(current,"amcs",si,"0")
     //! i end
     //! i makechange(current,"Ufn1","1","105.")
     //! i makechange(current,"Ufn1","2","150.")
     //! i makechange(current,"Ufn1","3","200.")
     //! i makechange(current,"Ufn1","4","260.")
     
     
     //! i createobject("AEsf", FREEZING_FIELD_ABIL_ID)
     //! i makechange(current,"anam", "Freezing Field")
     //! i makechange(current,"alev", "3")
     //! i makechange(current,"aart", "ReplaceableTextures\\CommandButtons\\BTNFreezingBreath.blp")
     //! i makechange(current,"arar", "ReplaceableTextures\\CommandButtons\\BTNFreezingBreath.blp")
     //! i makechange(current,"aret", "Learn |cffffcc00F|rreezing Field - [|CFF0960B8Level ".. string.char(37) .."d|r]")
     //! i makechange(current,"arut", "Summons multi explosions around the Jaina damaging enemys and slowing them for <"..FREEZING_FIELD_DAMAGE_ID..",Dur1> seconds. |n|n|cFF0960B8Level 1|r -  Each Explosion deals <"..FREEZING_FIELD_DAMAGE_ID..",DataA1> damage.|n|cFF0960B8Level 2|r -  Each Explosion deals <"..FREEZING_FIELD_DAMAGE_ID..",DataA2> damage.|n|cFF0960B8Level 3|r -  Each Explosion deals <"..FREEZING_FIELD_DAMAGE_ID..",DataA3> damage.|nLast <"..FREEZING_FIELD_ABIL_ID..",HeroDur1> seconds.|n|n|cffff0000Channeling|r")
     
     //! i local i = 0
     //! i for i=1, 3 do
        //! i local si = tostring(i)
        //! i makechange(current,"atar",si,"Self")
        //! i makechange(current,"Esf1",si,"0.")
        //! i makechange(current,"Esf2",si,"4.")
  //! i makechange(current,"Esf3",si,"0.")
        //! i makechange(current,"aare",si,"0.")
  //! i makechange(current,"ahdu",si,"4.1")
        //! i makechange(current,"adur",si,"4.1")
        //! i makechange(current,"acdn",si,"10")
  //! i makechange(current,"abuf",si,nil)
        //! i makechange(current,"aeff",si,nil)
  //! i makechange(current,"atp1",si,"|cffffcc00F|rreezing Field - [|CFF0960B8Level "..si.."|r]")
  //! i makechange(current,"aub1",si,"Summons multi explosions around the Jaina damaging enemys and slowing them for <"..FREEZING_FIELD_DAMAGE_ID..",Dur"..si.."> seconds. Each Explosion deals <"..FREEZING_FIELD_DAMAGE_ID..",DataA"..si.."> damage. |n|nLast <"..FREEZING_FIELD_ABIL_ID..",HeroDur"..si.."> seconds.|n|cffff0000Channeling|r")
     //! i end
     //! i makechange(current,"amcs","1","200")
     //! i makechange(current,"amcs","2","250")
     //! i makechange(current,"amcs","3","300")
     
     //! i if (FREEZING_FIELD_IMPROVED_ABIL_ID ~= nil) then
   //! i createobject("AEsf", FREEZING_FIELD_IMPROVED_ABIL_ID)
   //! i makechange(current,"anam", "Freezing Field")
   //! i makechange(current,"ansf", " ( Upgraded )")
   //! i makechange(current,"alev", "3")
   //! i makechange(current,"aart", "ReplaceableTextures\\CommandButtons\\BTNFreezingBreath.blp")
   //! i makechange(current,"arar", "ReplaceableTextures\\CommandButtons\\BTNFreezingBreath.blp")
   //! i makechange(current,"aret", "Learn |cffffcc00F|rreezing Field - [|CFF0960B8Level ".. string.char(37) .."d|r]")
   //! i makechange(current,"arut", "Summons multi explosions around the Jaina damaging enemys and slowing them for <"..FREEZING_FIELD_DAMAGE_ID..",Dur1> seconds. |n|n|cFF0960B8Level 1|r -  Each Explosion deals <"..FREEZING_FIELD_DAMAGE_ID..",DataA2> damage.|n|cFF0960B8Level 2|r -  Each Explosion deals <"..FREEZING_FIELD_DAMAGE_ID..",DataA3> damage.|n|cFF0960B8Level 3|r -  Each Explosion deals <"..FREEZING_FIELD_DAMAGE_ID..",DataA4> damage.|nLast <"..FREEZING_FIELD_IMPROVED_ABIL_ID..",HeroDur1> seconds.|n|n|cffff0000Channeling|r")
   
   
   //! i local i = 0
   //! i for i=1, 3 do
   //! i local si = tostring(i)
   //! i makechange(current,"atar",si,"Self")
   //! i makechange(current,"Esf1",si,"0.")
   //! i makechange(current,"Esf2",si,"4.")
   //! i makechange(current,"Esf3",si,"0.")
   //! i makechange(current,"aare",si,"0.")
   //! i makechange(current,"ahdu",si,"4.1")
   //! i makechange(current,"adur",si,"4.1")
   //! i makechange(current,"acdn",si,"10")
   //! i makechange(current,"abuf",si,nil)
   //! i makechange(current,"aeff",si,nil)
   //! i makechange(current,"atp1",si,"|cffffcc00F|rreezing Field - [|CFF0960B8Level "..si.."|r]")
   //! i makechange(current,"aub1",si,"Summons multi explosions around the Jaina damaging enemys and slowing them for <"..FREEZING_FIELD_DAMAGE_ID..",Dur"..tostring(i+1).."> seconds. Each Explosion deals <"..FREEZING_FIELD_DAMAGE_ID..",DataA"..tostring(i+1).."> damage. |n|nLast <"..FREEZING_FIELD_IMPROVED_ABIL_ID..",HeroDur"..si.."> seconds.|n|cffff0000Channeling|r")
            //! i makechange(current,"amcs",si,tostring(150+50*i))
   //! i end

  //! i end
  
  //! i if (FREEZING_FIELD_IMPROVED_ABIL_ID ~= nil or CHAIN_FROST_IMPROVED_ABIL_ID ~= nil) then
  //! i createobject("ANeg", AGHANIM_SCEPTER_ABIL_ID)
  //! i makechange(current,"aart", "ReplaceableTextures\\CommandButtons\\BTNINV_Wand_05.blp")
  //! i makechange(current,"Neg3","1", FREEZING_FIELD_ABIL_ID..","..FREEZING_FIELD_IMPROVED_ABIL_ID)
  //! i if (CHAIN_FROST_IMPROVED_ABIL_ID ~= nil) then
   //! i makechange(current,"Neg4","1", CHAIN_FROST_ABIL_ID..","..CHAIN_FROST_IMPROVED_ABIL_ID)
  //! i else
   //! i makechange(current,"Neg4","1", nil)
  //! i end
  //! i makechange(current,"Neg5","1", nil)
  //! i makechange(current,"Neg6","1", nil)
  //! i makechange(current,"Neg1","1", "0.")
  //! i makechange(current,"Neg2","1", "0.")
  //! i makechange(current,"aher", false)
  //! i makechange(current,"abuf","1", nil)
  //! i makechange(current,"alev", "1")
  //! i makechange(current,"arac", "nightelf")
  //! i makechange(current,"anam", "CF & FF Upgrader")
  //! i end
//! endexternalblock

       */
    // ^
    // |
// Change me from */ to // and then back to */ after saving and reopening the map
// ============================================================================================
[B]


Hope you enjoy the spell!

~Dark Dragon


Keywords:
frost, dota, ice, field, freezing, freezing field, other
Contents

Spell - Freezing Field (Map)

Reviews
PurplePoot: When you use Position of FF_Caster offset by (blah), the Position of FF_Caster leaks too. However, enough of the leaks are fixed that ~approved~. Please fix the rest if you find time, though.

Moderator

M

Moderator

PurplePoot:

When you use Position of FF_Caster offset by (blah), the Position of FF_Caster leaks too. However, enough of the leaks are fixed that ~approved~. Please fix the rest if you find time, though.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
JASS:
            set l[i] = Location( PolarProjectionX( GetLocationX( udg_FF_Point ), 75, 10 * I2R(i) ), PolarProjectionY( GetLocationY( udg_FF_Point ), 75, 10 * I2R(i) ) )
            call CreateNUnitsAtLoc( 1, Grf_RawCode(), p, l[i], ((10 * I2R(i)) - 90) )
            set udg_u[i] = GetLastCreatedUnit()

Could be

JASS:
set udg_u[i] = CreateUnit(p,Grt_RawCode(),PolarProjectionX( GetLocationX( udg_FF_Point ), 75, 10 * I2R(i) ),PolarProjectionY( GetLocationY( udg_FF_Point ), 75, 10 * I2R(i) ),((10 * I2R(i)) - 90))

(same thing with other instances of CreateNUnitsAtLoc)

Also, I suggest moving completely to coordinates as opposed to locations.

Also, try to calculate directly in radians for efficiency; just remember that pi radians = 180 degrees, and 2pi radians = 360 degrees.

Fix these up (a large part of the criticism) and I'll give you some more ;)
 

vhx

vhx

Level 3
Joined
Jan 15, 2008
Messages
36
Good job. Only problem I have with this spell is that when the loop starts to kick in, the
Code:
    //=========================
    // Create Effects on caster
    set bj_lastCreatedEffect = AddSpecialEffectTarget( &quot;Abilities\\Spells\\Items\\TomeOfRetraining\\TomeOfRetrainingCaster.mdl&quot;, udg_FF_Caster, &quot;origin&quot; )
    call DestroyEffect( bj_lastCreatedEffect )
    //=========================
Begins to double the lag the spell should cause. I just took it out and called it through a trigger so it shows up once and it works fine.
 
Level 8
Joined
Mar 23, 2007
Messages
302
is this meant to be MUI ?
cus as i placed 11 IceMages , set reqierd lvl from 6 to 1 and let them cast...
hell, after the 2 cast it showd me a Error message,...

as i continued,
holy sh*t my PC was frozen too, WC3 stoped completly and i hab to terminate wc3.

Edit : here is a link to what happens
http://bildupload.sro.at/p/234428.html
and the iceEffect circle stays for ever.
 
Here is update you needed no locations used less function usage and its as max as possible natives used and constant functions. All is updated other the fully GUI 4x triggers which is not MUI and is ofc pathetic code in your map. But GUI made for jass setup whit global variables will do everything for you in second its 75% faster for yu to copy 2x triggers and edit in GUI only a few globals then all 4x trigger of GUI.

If you have a problem or dont know how to do something mail me at &lt;[email protected]&gt; or post comment here.

Have fun!
 
Well this spell is made in JASS but as well it is made in GUI and in JASS/GUI. I suggest you using JASS/GUI 2x triggers if you dont know JASS because its great in performances.

How it is done you ask?

Check its core in trigger editor. Check GUI or JASS but in GUI you dont have custom graphics, so check Jass code. There you will see how its done. You can find That code in Trigger Editor (F4). Find Freezing Field jass or something like that cant remember how i called trigger exactly.
 
hmm i am not sure what exactly do you mean this is vjass version of ... I never heard of him nor did i play his map... if thats what you mean... this is my first uploaded spell here and at that time i really liked some dota spells so i made this the first one and about coding if by any means you mean i copied something or whatever, its not true I made it all from scratch by myself... So yeah i hope i answered on your question/comment... so again don't worry i made all of this by myself and if its anyone's idea then its IceFrog's from dota but i injected custom graphics in my code... thats all and i wrote that in description

If you have any more questions fell free to ask!
~Dark Dragon
 
Level 4
Joined
Dec 15, 2007
Messages
108
i find a way =) and i works fine ^^
JASS:
		// Causes a single explosion
		public method Explode takes nothing returns nothing
			local unit u = null
			local real ang = this.Angle()
			local real dist = this.Distance()
			
			set u = CreateUnit(this.p, DUM_RAWCODE, this.x + dist * Cos(ang), this.y + dist * Sin(ang), bj_UNIT_FACING)
			call UnitAddAbility(u, DFN_RAWCODE)
			call SetUnitAbilityLevel(u, DFN_RAWCODE, this.lvl)
			call IssueTargetOrder(u, "frostnova", u)
                             call UnitAddAbility(u, 'Aloc')  // <--- add here the locust ability after he casts the spell gl hf =)
			call UnitApplyTimedLife(u, 'BTLF', 0.5)
			set u = null
			
			call SetRandomSeed(GetRandomInt(0, 1000000))
		endmethod

just add the locust ability after he cast the spell on himself =)
 
Level 17
Joined
Mar 2, 2009
Messages
332
This is Great i downloaded it before....i will download new version when i downlaod JassNewGenPack.....but what i remember before this was AWESOME ...and you made scepter from DotA if i'm not wrong...5/5 and ofc +rep later when i spread some...
Only thing i don't like was that green spots ....i dunno maybe you fixed it allready..
 
This is Great i downloaded it before....i will download new version when i downlaod JassNewGenPack.....but what i remember before this was AWESOME ...and you made scepter from DotA if i'm not wrong...5/5 and ofc +rep later when i spread some...
Only thing i don't like was that green spots ....i dunno maybe you fixed it allready..

hmm green spots? i am not sure what do you mean but ill fix any bug or problem so feel free to tell me about it if you find anything when you get JNGP!
 
I checked and i can only say AWESOME! good job....no green spots this time and only thing i would change is the duration to little more time...but that's not necessary... 5/5 +rep

thanks for your time testing and commenting! yeah that duration can be easy changed. simply go to object editor and change the duration of Freezing Field spell.

i guess spell would be a little imba if i increase duration, ohhh for me its already imba :p

anyway thanks for comment +rep!
~DD
 
Level 17
Joined
Nov 12, 2016
Messages
785
i dont like this spell very much nice effects but its to short plus i dont like when it changes the grounds trrain.

but some things are interesting such as how did you made the freezing breath ability to fall from the sky ??? how did you do that ?? dose it involve hard work and triggers or there is a way to make it happen ??
 
i dont like this spell very much nice effects but its to short plus i dont like when it changes the grounds trrain.

but some things are interesting such as how did you made the freezing breath ability to fall from the sky ??? how did you do that ?? dose it involve hard work and triggers or there is a way to make it happen ??

Hi,

1) you can alter duration of spell (Freezing Field in object editor, change channel duration), as well you can disable the terrain change

2)
JASS:
constant    boolean             DO_PAINT_FIELD                  = true;
.

change that line in trigger editor from "true" to "false".

3) It involvs trigger editor code, furthermore you can disable freezing breath from falling from the sky by changing

JASS:
constant    boolean             ICE_FALL_USE                    = true;

change it from true to false.

Regards!
~DarkDragon
 
Level 17
Joined
Nov 12, 2016
Messages
785
umm i got all that but i want too know how too make freezing breath from falling from the sky in any rain of fire starfall or blizzard ability
 
umm i got all that but i want too know how too make freezing breath from falling from the sky in any rain of fire starfall or blizzard ability

Hi,

the way i made it is:

1) create dummy unit at initial height "z"
2) add special effect freezing breath to dummy
3) create timed trigger which will every 0.02 - 0.04 seconds move the dummy.

that way you make effect move with dummy unit.

Regards!
~DD
 
Top