1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  3. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  4. The poll for Hive's 12th Concept Art Contest is up! Go cast your vote for your favourite genie!
    Dismiss Notice
  5. Travel to distant realms and encounter scenes unknown to the common folk. The Greatest of Adventures is upon us with the 8th Cinematic Contest. Join in on a fun ride.
    Dismiss Notice
  6. The 18th Icon Contest is ON! Choose any ingame unit and give him/her Hero abilities. Good luck to all.
    Dismiss Notice
  7. Contestants are to create a scene set in the Stone Age. Come and see what you can come up with. We wish you the best of luck!
    Dismiss Notice
  8. Colour outside the lines! Techtree Contest #13 is a go. The contest is optionally paired.
    Dismiss Notice
  9. Greetings cerebrates, our Swarm needs new spawners that will have numerous children. Join the HIVE's 31st Modeling Contest - Spawners and Spawned! The contest is optionally paired.
    Dismiss Notice
  10. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Spell - Max Bash 2.1c

Submitted by Dark_Dragon
This bundle is marked as approved. It works and satisfies the submission rules.
Well just another (DotA) spell made by me!
This time i was requested to make it.


Description
(Passive ability)

Gives a percent chance to deal extra damage, send target to air and push target afterwards. Upon landing units take extra damage. Sliding unit deals splash bash that slightly pushes units and deals 30% damage from original bash.

Level 1 - 15% chance, 2.6x damage, 30 landing damage, 200 distance push.
Level 2 - 17% chance, 3.4x damage, 40 landing damage, 230 distance push.
Level 3 - 20% chance, 4.5x damage, 55 landing damage, 270 distance push.



Cant push a building!




Credits

IceFrog: Used it in dota
Venom: Icon (seems that DIS one does not work)
nerovesper: Reason why spell is here (request)

Hive for hosting this spell
Blizzard for making game




Version 2.0 - Max Bash Remasterd
- Totally recoded in zinc
- Spell now has option for splash bash
- Spell does not trigger when spell damage is dealt
- Now has bounce effect, so that units do not get stuck in unpathable areas



Version 2.1 - Spell Update
- Added option for height launching
- Spell can be adjusted to have just land slide, land slide with parabolic motion or just height launch

(This update was requested by
hemmedo)


Version 2.1b - Spell Update
- Melee units now can't attack airborn units


Version 2.1c - Spell Update
- Uses new DD Library and compatible with Warcraft 3 v1.30




Code
Code (vJASS):

//TESH.scrollpos=0
//TESH.alwaysfold=0
// *******************************************************************************
//                          Spell: Max Bash by Dark Dragon
//
//                 Credits: IceFrog    -> Used in Dota! Idea is by someone...
//                          Venom      -> Icon
//                          nerovesper -> Request
//
//
//                              Installation:
//
//  1. Copy 'DD Library' and this trigger to your map
//  2. Copy abilitie and buff 'Max Bash' to your map
//  3. Export and import "DDSpells\MaxBashHit.mdx" and icons with same path to your map if you are going to use them
//  4. Modifie data below to mach your map and other constants
//
// * Enjoy!
// *******************************************************************************






//! zinc
// *** This is the max bash spell library ***
library MaxBash requires DDLib
{
 // ======================================================================
 //     *** Editable constants ***
 // ======================================================================
 
 // -------------------------------------------------------
 // This is the raw code of max bash ability
 // Default: 'MBsh'
 constant integer        MAX_BASH_ID                  = 'MBsh';
 
 // -------------------------------------------------------
 // This is the raw code of max bash buff
 // Default: 'MBed'
 constant integer  MAX_BASH_BUFF_ID    = 'MBed';
 
 // ----------------------------------------------------------
 // Push model file effect
 // Default: Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl
    constant string         PUSH_MODEL_FILE               = "Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl";
 
 // ----------------------------------------------------------
 // Push model file effect of sliding unit, attach point
 // Default: foot
 constant string   PUSH_EFFECT_ATT_POINT   = "foot";
 
 // ----------------------------------------------------------
 // If custom water effect is wanted set this to true
 // Default: true
 constant boolean  USE_WATER_FILE     = true;
 
 // ----------------------------------------------------------
 // Push model file effect on water
 // Default: Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl
 constant string   PUSH_MODEL_WATER_FILE   = "Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl";
 
 // -------------------------------------------------------
 // On push file (when ability is triggerd) applay this effect
 // Default: DDSpells\\MaxBashHit.mdx
    constant string         ON_PUSH_FILE              = "DDSpells\\MaxBashHit.mdx";
 
 // -------------------------------------------------------
 // How often to create "PUSH_MODEL_FILE" effect
 // Default: .1
 constant real   PUSH_EFFECT_INTERVAL   = .15;
 
    // -------------------------------------------------------  
    // On which point of attacker "ON_PUSH_FILE" is added?
    // Default: weapon
    constant string         ATTACH_POINT              = "weapon";
 
 // -------------------------------------------------------  
    // Effect generated on target unit when its hit
    // Default: none
    constant string         BASH_HIT_EFFECT_FILE   = "";
 constant string   BASH_HIT_EFFECT_FILE_ATT_POINT = "origin";
 
 // -------------------------------------------------------  
    // Effect generated when unit hits the ground
    // Default: Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl
    constant string         BASH_HIT_GROUND_EFFECT_FILE  = "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl";
 
 // -------------------------------------------------------  
    // Effect generated when unit hits/impacts the water, requires USE_WATER_FILE to be true
    // Default: Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl
 constant string   BASH_IMPACT_WATER_EFFECT_FILE = "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl";
 
 // -------------------------------------------------------  
    // While unit is sliding, what will be its animation speed in percentage
    // Default: 65.
 constant real   UNIT_ANIM_SPEED     = 65.;
 
 // -------------------------------------------------------  
    // While unit is sliding, what will be its animation
    // Default: attack
 constant string   UNIT_ANIM_NAME     = "attack";
 
 // -------------------------------------------------------  
    // Extra damage that bash deals seted up by level "function BashDamage" will
 // be treated as extra/bonus damage or as percentage of dealt damage,
 // if true percent damage will be dealt
    // Default: true
 constant boolean  BASH_DAMAGE_AS_PERCENTAGE  = true;
 
    // -------------------------------------------------------  
    // This is speed in game coordinates, of how fast unit is pushed away
    // defined start and end speeds of pushed unit
 // start speed = initial speed, end speed = speed before stopping
    // Default: 350 / 50
    constant real           PUSH_SPEED_START         = 350.;
    constant real           PUSH_SPEED_END           = 50.;
 
 // -------------------------------------------------------
    // Enemy units that collide with sliding unit will be slightly pushed too?
    // Default: true
 constant boolean  ENABLE_SPLASH_BASH    = true;
 
 // -------------------------------------------------------
    // Damage splashed on extra colliding units in percentage
    // Default: 30%
 constant real   SPLASH_DAMAGE_PERCENTAGE  = 30.;
 
 // -------------------------------------------------------
    // The min speed at which sliding unit has to be to cause pushing other unit
    // Default: 175.
 constant real   SPLASH_BASH_NEED_SPEED   = 175.;
 
 // -------------------------------------------------------
    // The area/radius around sliding unit to check for splash damage
    // Default: 120.
 constant real   SPLASH_BASH_SCAN_R    = 120.;
 
 // -------------------------------------------------------
    // How often to check for splash bash damage
    // Default: .2
 constant real   SPLASH_BASH_INTERVAL   = .2;
 
 // -------------------------------------------------------
    // Some units have default ground offset height, what is that max height
 // so that bash does treat this units as grounded
    // Default: 50.
 constant real   SPLASH_BASH_MAX_HEIGHT   = 50.;
 
 // -------------------------------------------------------
    // Should trees be destroyed?
    // Default: true
    constant boolean        DESTROY_TREES             = true;
 
 // -------------------------------------------------------
 // How often to clear trees
 // Default: .2
 constant real   CLEAR_TREES_INTERVAL   = .2;
 
 // -------------------------------------------------------
 // Range in which to clear trees
 // Default: 160.
 constant real   CLEAR_TREES_RADIUS    = 160.;
 
 // -------------------------------------------------------
 // Range at which to check if pathing is unpathable, for bounce code to be triggerd
 // Default: 60.
 constant real   BOUNCE_DETECT_RANGE    = 60.;
 
    // -------------------------------------------------------  
    // Should floating text be created?
    // Default: true
    constant boolean        ALLOW_FLOATING_TEXT       = true;
 
 // -------------------------------------------------------  
    // When units are killed by bash display KO or damage dealt
    // Default: true
 constant boolean  USE_KO_TEXT      = true;
 
    // -------------------------------------------------------  
    // The duration of floating text in seconds
    // Default: 4.25
    constant real           FLOATING_TEXT_DURATION    = 3.;
 
 // -------------------------------------------------------  
    // The color of text rgb transparency in percentage
    // Default: 100. / 100. / 100. / 20.
 constant real   FLOATING_TEXT_RED    = 100.;
 constant real   FLOATING_TEXT_GREEN    = 100.;
 constant real   FLOATING_TEXT_BLUE    = 100.;
 constant real   FLOATING_TEXT_TRANS    = 20.;
 
 // -------------------------------------------------------------
    constant key   UNIT_BASH_KEY;
 // -------------------------------------------------------------
 //          *** Level data setup here ***
 
 
 // -------------------------------------------
 // *** The bash damage per level ***
    // Default: 2.6 / 3.4 / 4.5
 function BashDamage(integer level) -> real {
  real bash_damage[];
 
  bash_damage[1] = 2.6;
  bash_damage[2] = 3.4;
  bash_damage[3] = 4.5;
 
  return bash_damage[level];
 }
 
 // -------------------------------------------
 // *** The bash push distance per level ***
    // Default: 200. / 230. / 270.
 function BashPushDistance(integer level) -> real {
  real bash_range[];
 
  bash_range[1] = 200.;
  bash_range[2] = 230.;
  bash_range[3] = 270.;
 
  return bash_range[level];
 }
 
 // -------------------------------------------
 // *** The bash push height per level ***
    // Default: 90. / 110. / 130.
 function BashPushHeight(integer level) -> real {
  real bash_height[];
 
  bash_height[1] = 90.;
  bash_height[2] = 110.;
  bash_height[3] = 130.;
 
  return bash_height[level];
 }
 
 // -------------------------------------------
 // *** The bash push height travel percentage per level ***
 // This setting says at which percentage of path will unit land
    // Default: 30. / 34. / 39.
 function BashPushHeightTravelPerc(integer level) -> real {
  real bash_height_travel_perc[];
 
  bash_height_travel_perc[1] = 30.;
  bash_height_travel_perc[2] = 34.;
  bash_height_travel_perc[3] = 39.;
 
  return bash_height_travel_perc[level];
 }
 
 // -------------------------------------------
 // *** The damaged dealt by impact
    // Default: 30. / 40. / 55.
 function BashPushGroundImpactDamage(integer level) -> real {
  real bash_ground_impact_damage[];
 
  bash_ground_impact_damage[1] = 30.;
  bash_ground_impact_damage[2] = 40.;
  bash_ground_impact_damage[3] = 55.;
 
  return bash_ground_impact_damage[level];
 }
 
 
 // -------------------------------------------
 // *** If splash bash is activated, this will filter which are proper units to be pushed.
 function SplashBashFilter(unit filter_unit, player bashPlayer) -> boolean {
  return  !IsUnitType(filter_unit, UNIT_TYPE_DEAD)       &&
    IsUnitEnemy(filter_unit, bashPlayer)        &&
    IsUnitType(filter_unit, UNIT_TYPE_GROUND)      &&
    !BlzIsUnitInvulnerable(filter_unit)        &&
    !IsUnitType(filter_unit, UNIT_TYPE_STRUCTURE)     &&
    !DDIsUnitWard(filter_unit);
 }
 
 // ==================================================================================
 //       *** End spell modification ***
 // ==================================================================================
 
 // ---------------------------------------------------------
 // *** Bash data structure
 struct bash {
  private {
   unit   b, s;
   real   dist, mxdist, impdist;
   real   dx, dy, initZ;
   p_real  z_parab;
   real  dmg;
   p_real   vec;
   integer  p, lvl;
   boolean  hit_ground;
  }
 
  /// ----------------------------------------------------------------
 
  // ***
  static method create(integer castplayer, unit bashingUnit, unit whichUnit, integer lvl, real distance, real radians, real damage) -> bash {
   bash this = allocate();
 
   s    = bashingUnit;
   b    = whichUnit;
   dist   = distance;
   mxdist  = SquareRoot(distance);
   dx   = Cos(radians);
   dy   = Sin(radians);
   vec   = pVector(GetUnitX(b), GetUnitY(b), GetUnitFlyHeight(b));
   p   = castplayer;
   dmg   = damage;
   hit_ground  = BashPushGroundImpactDamage(lvl) < 1.;
 
   // -------------------------
   // a(x-x0)^2 + y0 = a(x^2 - 2x*x0 + x0^2) + y0 = a*(x)^2 - 2*a*x0*(x) + a*x0^2+y0
   // -------------------------
   // x0 = mxDist(100-perc/2)/100
   // y0 = vec[2] + h
   // a = -h / (mtd/2)^2
   // b = -2*a*x0
   // c = y0+a*x0^2
   z_parab  = p_real.create();
   z_parab[0]  = -BashPushHeight(lvl) / Pw_2(BashPushHeightTravelPerc(lvl)*distance/200.);   // a = -h / (mtd/2)^2
   z_parab[1]  = -2. * z_parab[0] * ((100.-BashPushHeightTravelPerc(lvl)/2.)*distance/100.);             // b = -2*a*x0
   z_parab[2]  = (BashPushHeight(lvl) + vec[2]) + z_parab[0]*Pw_2((100.-BashPushHeightTravelPerc(lvl)/2.)*distance/100.);     // c = a*x0^2+y0
   this.lvl  = lvl;
   impdist  = (100.-BashPushHeightTravelPerc(lvl))*distance/100.;
   initZ  = vec[2];
 
   DDSet(b, UNIT_BASH_KEY, this);
   UnitAddAbility(b, 'Amrf');
   UnitRemoveAbility(b, 'Amrf');
   SetUnitTimeScale(b, UNIT_ANIM_SPEED*.01);
   if (!IsUnitType(b, UNIT_TYPE_DEAD)) {
    SetUnitAnimation(b, UNIT_ANIM_NAME);
    QueueUnitAnimation(b, "stand");
   }
 
   return this;
  }
 
  // ***
  method destroy() {
   DDSet(b, UNIT_BASH_KEY, p_null);
   SetUnitTimeScale(b, 1.);
   vec.destroy();
   z_parab.destroy();
   s = null;
   b = null;
   deallocate();
  }
 
  method operator IsAirborn() -> boolean { return !hit_ground; }
 
  /// ----------------------------------------------------------------
  //* splash code
  private method TryDoSplashBash() {
   integer i;
   unit u;
 
   // *** Skip splash if unit is in air ***
   if (vec[2] > SPLASH_BASH_MAX_HEIGHT)
    return;
 
   // --------------------------------------
   // *** pick units to be splash bashed
   DDGroupFillMemArea(vec[0], vec[1], SPLASH_BASH_SCAN_R, p, function() -> boolean {
    return SplashBashFilter(GetFilterUnit(), Player(DDMemUnitData())) && DDGet(GetFilterUnit(), UNIT_BASH_KEY) == p_null;
   });
 
   // --------------------------------------------------------------
   // *** Now launch them in there respective directions and speeds
   for(i=0; i < DDMemUnitN(); i+=1) {
    u = DDMemUnit(i);
 
    // *** Do damage and bash the target ***
    UnitDamageTarget(s, u, dmg*SPLASH_DAMAGE_PERCENTAGE*.01, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS);
    BashExecute.evaluate(p, s, u, lvl, dist, Atan2(GetUnitY(u)-vec[1], GetUnitX(u)-vec[0]), dmg);
 
    // *** Floating text add? ***
    static if (ALLOW_FLOATING_TEXT)
     static if (USE_KO_TEXT)
      if (IsUnitType(u, UNIT_TYPE_DEAD))
       DDNewTextTagUnit(u, "|cffff0000KO!!!|r", FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
      else
       DDNewTextTagUnit(u, "+"+I2S(R2I(dmg*SPLASH_DAMAGE_PERCENTAGE*.01)), FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
     else
      DDNewTextTagUnit(u, "+"+I2S(R2I(dmg*SPLASH_DAMAGE_PERCENTAGE*.01)), FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
   }
 
  }
 
  // -------------------------------------------------------------------------
  // * checks and performs ground impact as well as dealing damage and displaying floating text
  method CheckGroundHit() {
   if (impdist > dist) {
    vec[2] = initZ;
    if (!hit_ground) {
     hit_ground = true;
     static if (USE_WATER_FILE)
      if (IsTerrainPathable(vec[0], vec[1], PATHING_TYPE_FLOATABILITY))
       DestroyEffect(AddSpecialEffect(BASH_HIT_GROUND_EFFECT_FILE, vec[0], vec[1]));
      else
       DestroyEffect(AddSpecialEffect(BASH_IMPACT_WATER_EFFECT_FILE, vec[0], vec[1]));
     else
      DestroyEffect(AddSpecialEffect(BASH_HIT_GROUND_EFFECT_FILE, vec[0], vec[1]));
   
     if (!IsUnitType(b, UNIT_TYPE_DEAD)) {
      UnitDamageTarget(s, b, BashPushGroundImpactDamage(lvl), true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS);
      // *** Floating text add? ***
      static if (ALLOW_FLOATING_TEXT)
       static if (USE_KO_TEXT)
        if (IsUnitType(b, UNIT_TYPE_DEAD))
         DDNewTextTagUnit(b, "|cffff0000KO!!!|r", FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
        else
         DDNewTextTagUnit(b, "+"+I2S(R2I(BashPushGroundImpactDamage(lvl))), FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
       else
        DDNewTextTagUnit(b, "+"+I2S(R2I(BashPushGroundImpactDamage(lvl))), FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
     }
    }
   }
  }
 
  /// ----------------------------------------------------------------
  //* primary push code
  method Launch() {
   DDStartTim(DD_INTERVAL, true, this, static method() {
    bash   this   = bash( DDTimData() );
    integer  tick  = DDTimTick();
    real   speed   = DD_INTERVAL * (PUSH_SPEED_END + ( (PUSH_SPEED_START-PUSH_SPEED_END)/mxdist )*SquareRoot(dist));
    // basic formula for speed: y = a*sqrt(x) + b
 
    // ----------------------------------
    // *** Position calcs
    dist  -= speed;
    vec[0] += speed * dx;
    vec[1] += speed * dy;
    vec[2]  = (z_parab[0]*Pw_2(dist)) + (z_parab[1]*dist) + (z_parab[2]);
 
    // ------------------------------------
    // *** Check if hit ground ***
    CheckGroundHit();
 
    // ----------------------------------
    // *** Motion
    SetUnitX(b, vec[0]);
    SetUnitY(b, vec[1]);
    SetUnitFlyHeight(b, vec[2], 0.);
 
    // ----------------------------------
    // *** Push Effects
    if (ModuloReal(tick*DD_INTERVAL, PUSH_EFFECT_INTERVAL) < DD_INTERVAL)
     static if (USE_WATER_FILE)
      if (IsTerrainPathable(vec[0], vec[1], PATHING_TYPE_FLOATABILITY) || vec[2] > SPLASH_BASH_MAX_HEIGHT)
       DestroyEffect(AddSpecialEffectTarget(PUSH_MODEL_FILE, b, PUSH_EFFECT_ATT_POINT));
      else
       DestroyEffect(AddSpecialEffectTarget(PUSH_MODEL_WATER_FILE, b, PUSH_EFFECT_ATT_POINT));
     else
      DestroyEffect(AddSpecialEffectTarget(PUSH_MODEL_FILE, b, PUSH_EFFECT_ATT_POINT));
 
    // ----------------------------------------
    // *** Check if trees are in the way
    static if (DESTROY_TREES)
     if (ModuloReal(tick*DD_INTERVAL, CLEAR_TREES_INTERVAL) < DD_INTERVAL) {
   
      DDEnumDestsInRange(vec, CLEAR_TREES_RADIUS, null, function() {
       if (DDIsDestructableTree(GetEnumDestructable()))
        KillDestructable(GetEnumDestructable());
      });
     }
 
    // ---------------------------------------------------------
    // *** Check for bounce/collision with unpathable points
    if (ModuloReal(tick*DD_INTERVAL, CLEAR_TREES_INTERVAL) < DD_INTERVAL) {
     if (IsTerrainPathable(vec[0]+BOUNCE_DETECT_RANGE*dx, vec[1], PATHING_TYPE_WALKABILITY))
      dx = -dx;
     else if (IsTerrainPathable(vec[0], vec[1]+BOUNCE_DETECT_RANGE*dy, PATHING_TYPE_WALKABILITY))
      dy = -dy;
    }
 
    // ----------------------------------------
    // *** Check if there are any units to be splash bashed
    static if (ENABLE_SPLASH_BASH)
     if (speed > SPLASH_BASH_NEED_SPEED*DD_INTERVAL && ModuloReal(tick*DD_INTERVAL, SPLASH_BASH_INTERVAL) < DD_INTERVAL)
      TryDoSplashBash();
   
    // ----------------------------------
    // *** Check to quit push
    if (dist <= 0.) {
     PauseUnit(b, false);
     destroy();
     DDQuitTim();
    }
   });
  }
 }
 
 // *** Bash function that will be called from above and below
 function BashExecute(integer p, unit basher, unit u, integer lvl, real dist, real radians, real dmg) {
  // *** Now pause the victim ***
  PauseUnit(u, true);
  DestroyEffect(AddSpecialEffectTarget(BASH_HIT_EFFECT_FILE, u, BASH_HIT_EFFECT_FILE_ATT_POINT));
  bash.create(p, basher, u, lvl, dist, radians, dmg).Launch(); /// *** Will be auto destroyed
 }
 
 // ==================================================================================
 //        *** Initialization ***
 function onInit() {
  trigger t = CreateTrigger();
 
  TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED);
  DDTriggerRegisterAnyUnitDamaged(t);
  TriggerAddCondition(t, function() -> boolean {
   unit       u;
   unit       v;
   integer   lvl;
   real  dmg = 0.;
   bash  b;
 
   // *** Attac
   if (GetTriggerEventId() == EVENT_PLAYER_UNIT_ATTACKED) {
    u = GetAttacker();
    v = GetTriggerUnit();
    b = DDGet(v, UNIT_BASH_KEY);
 
    if (b != p_null)
     if (IsUnitType(u, UNIT_TYPE_MELEE_ATTACKER) && b.IsAirborn)
      IssueImmediateOrder(u, "stop");
 
    u = null;
    v = null;
    return false;
   }
 
   u       = GetEventDamageSource();              // Damages source unit
   v       = GetTriggerUnit();                    // Victim unit
   lvl     = GetUnitAbilityLevel(u, MAX_BASH_ID);   // Spell level
 
 
   // --------------------------------------
   // *** Condition
   if (GetUnitAbilityLevel(v, MAX_BASH_BUFF_ID) == 0 || DDGet(v, UNIT_BASH_KEY) != p_null) {
    UnitRemoveAbility(v, MAX_BASH_BUFF_ID);
    u = null;
    v = null;
    return false;
   }
 
   // *** No future exec, prevent exec this trigger when we call "UnitDamageTarget" below ***
   DisableTrigger(GetTriggeringTrigger());
 
   // *** Clear the buff ***
   UnitRemoveAbility(v, MAX_BASH_BUFF_ID);
 
   // *** Primary damage ***
   static if (BASH_DAMAGE_AS_PERCENTAGE)
    dmg = GetEventDamage()*BashDamage(lvl);
   else
    dmg = BashDamage(lvl);
 
   BlzSetEventDamage(GetEventDamage() + dmg);
   //UnitDamageTarget(u, v, dmg, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS);

   // *** Apply custom effect ***
   DestroyEffect(AddSpecialEffectTarget(ON_PUSH_FILE, u, ATTACH_POINT));

   // *** Floating text add? ***
   static if (ALLOW_FLOATING_TEXT)
    static if (USE_KO_TEXT)
     if (IsUnitType(v, UNIT_TYPE_DEAD))
      DDNewTextTagUnit(v, "|cffff0000KO!!!|r", FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
     else
      DDNewTextTagUnit(v, "+"+I2S(R2I(dmg)), FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
    else
     DDNewTextTagUnit(v, "+"+I2S(R2I(dmg)), FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
   
 
   // *** Load main bash struct ***
   BashExecute(GetPlayerId(GetOwningPlayer(u)), u, v, lvl, BashPushDistance(lvl), Atan2(GetUnitY(v)-GetUnitY(u), GetUnitX(v)-GetUnitX(u)), dmg);

   // *** Allow next exec ***
   EnableTrigger(GetTriggeringTrigger());
     
   // *** Null locals ***
   u = null;
   v = null;
   return false;
  });
 }
}
//! 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 MAX_BASH_ABIL_ID     = "MBsh"
 //! i MAX_BASH_BUFF_ID     = "MBed"
 
 //! i -- =================================================================

     //! i setobjecttype("buffs")
     //! i createobject("BSTN", MAX_BASH_BUFF_ID)
     //! i makechange(current, "fart", "ReplaceableTextures\\CommandButtons\\PASBash.blp")
     //! i makechange(current, "ftat", "")
     //! i makechange(current, "fta0", "")
     //! i makechange(current, "fnam", "Max Bash")
     //! i makechange(current, "ftip", "Max Bash")
 
     //! i setobjecttype("abilities")
     //! i createobject("AHbh", MAX_BASH_ABIL_ID)
     //! i makechange(current,"anam", "Max Bash")
     //! i makechange(current,"aart", "ReplaceableTextures\\CommandButtons\\PASBash.blp")
     //! i makechange(current,"arar", "ReplaceableTextures\\CommandButtons\\PASBash.blp")
     //! i makechange(current,"abpx", "3")
     //! i makechange(current,"arpx", "3")
     //! i -- makechange(current,"alev", "3")
     //! i -- makechange(current,"arlv", "1")
     //! i -- makechange(current,"ahky", "H")
     //! i makechange(current,"arhk", "X")
     //! i makechange(current,"aret", "Learn Ma|cff109da9x|r Bash - [|cffffcc00Level ".. string.char(37) .."d|r]")
     //! i makechange(current,"arut", "|cffc0c0c0Gives a percent chance to deal extra damage and push target. Sliding unit deals splash bash that slightly pushes units and deals 30% damage from original bash. |r|n|n|cffffcc00Level 1|r - 15% chance, 2.6x damage, 200 distance push. |n|cffffcc00Level 2|r - 17% chance, 3.4x damage, 230 distance push. |n|cffffcc00Level 3|r - 20% chance, 4.5x damage, 270 distance push.")
     //! i makechange(current,"aub1","1","|cffc0c0c0Gives a 15% chance to deal extra 2.6x damage, push target 200 offset distance and deal 30% splash bash.|r")
     //! i makechange(current,"aub1","2","|cffc0c0c0Gives a 17% chance to deal extra 3.4x damage, push target 230 offset distance and deal 30% splash bash.|r")
     //! i makechange(current,"aub1","3","|cffc0c0c0Gives a 20% chance to deal extra 4.5x damage, push target 270 offset distance and deal 30% splash bash.|r")
   
     //! i local i = 0
     //! i for i=1, 3 do
        //! i local si = tostring(i)
        //! i makechange(current,"atar",si,"Enemy,Ground,Organic")
        //! i -- makechange(current,"aran",si,"99999.")
        //! i makechange(current,"Hbh1",si,tostring(13+(2*i)))
        //! i makechange(current,"abuf",si,"MBed")
        //! i makechange(current,"Hbh5",si,"1")
        //! i makechange(current,"Hbh3",si,"0.")
        //! i makechange(current,"atp1",si,"Max Bash - [|cffffcc00Level ".. si .."|r]")
     //! i end
     //! i makechange(current,"Hbh1","3","20.")
//! endexternalblock

       */

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

 


If you have any future questions, suggestions or found any bug feel free to comment!

Enjoy!
~Dark Dragon


Keywords:
passive, bash, dota, knockback
Previews
Contents

Spell - Max Bash 2.1c (Map)

Reviews
Moderator
19:03, 3rd Jun 2009 hvo-busterkomo: A decently developed knockback spell, with an effect on the acceptable level. Here's my complaints: 1. You shouldn't be using the readonly syntax. I don't see much reason to use it, as most people probably aren't...
  1. Dark_Dragon

    Dark_Dragon

    Joined:
    Jul 19, 2007
    Messages:
    596
    Resources:
    8
    Tools:
    1
    Spells:
    7
    Resources:
    8
    was my job and if u are happy with it then its great ;)
     
  2. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    hopefully I'm smart enough to know how to import this by reading :)

    as I'm not the best @jass nor vJass thought I know more in vJass then jass :S
     
  3. Dark_Dragon

    Dark_Dragon

    Joined:
    Jul 19, 2007
    Messages:
    596
    Resources:
    8
    Tools:
    1
    Spells:
    7
    Resources:
    8
    hehe thats why we all code in vJass ;) coz its easier :p
     
  4. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    that's why I code GUI cause else I don't get a thing in the script ;)
     
  5. Raziel_br

    Raziel_br

    Joined:
    Oct 13, 2008
    Messages:
    554
    Resources:
    0
    Resources:
    0
    What is ddup.j?
     
  6. EvilNico

    EvilNico

    Joined:
    Jul 16, 2008
    Messages:
    26
    Resources:
    0
    Resources:
    0
    yes giv me ddup.j
     
  7. aider

    aider

    Joined:
    Jul 14, 2010
    Messages:
    244
    Resources:
    2
    Maps:
    2
    Resources:
    2
    Yeah what is
    // *** Include ddup.j ***
    //! import "ddup.j"
    Getting error saying it cant find the file.

    I also remember I gave up on importing DD Universal Spell Pack cus of this strange mysterious file. The trigger back then had something with "Get ddup.j trigger", and the trigger that was named ddup.j had nothing in it except " //! import "ddup.j" ". What is it? It doesnt make sense..
    You can even save the TEST MAP and it doesnt work.. -5/5
     
    Last edited: Jun 10, 2011
  8. Maximum_Evil

    Maximum_Evil

    Joined:
    Nov 28, 2009
    Messages:
    1,527
    Resources:
    4
    Maps:
    4
    Resources:
    4
    I dont get it how im supposed to import this, the link is expired or does not exist...
     
  9. baassee

    baassee

    Joined:
    Nov 14, 2008
    Messages:
    3,220
    Resources:
    17
    Spells:
    14
    Tutorials:
    3
    Resources:
    17
    The file included code that the spells are using, dd although uploaded to the pastebin sad enough so basic the spells he made that require the file won't work.
     
  10. hemmedo

    hemmedo

    Joined:
    Jun 13, 2008
    Messages:
    276
    Resources:
    0
    Resources:
    0
  11. Diegoit

    Diegoit

    Joined:
    Apr 8, 2017
    Messages:
    1,197
    Resources:
    1
    Models:
    1
    Resources:
    1
    Perfect unit selection :infl_thumbs_up:
    Beauty terrain
     
  12. emil23

    emil23

    Joined:
    Jul 17, 2013
    Messages:
    222
    Resources:
    1
    Maps:
    1
    Resources:
    1
    Hey! its first time i copied jass trigger to my map. i didnt brother with jass triggers before because they seemed too hard for me.i am editing in gui. this is the knockback i used Spell - Max Bash 2.1c

    i coppied all jass triggers to my map + max bash abbility, and buff + dummy unit + chest item. after i openned map i made sure for dummy and max bash ability id to be same like in my map. and thats all


    i tested spell in game it worked perfectly. the problem is always after EXCATLY 20 minuts of game triggers from my map starts randomly running while they arent supossed to. and some of ai units also walks very strange just like they would be knocked back.i am sure knockback is reason of this :( this system is cool but sometimes it damages my gui triggers.or maybe i didnt install it correctly? insturction said about importing dummy model but i couldnot see it in that map with max bash spell

    btw i noticed that there are lines like
    // Change me from */ to // and then back to */ after saving and reopening the map
    // i gotta admit i didnt do that because i didnt notice it maybe it caused this problem?


    ALSO I REALISED SOMETHING IMPORTANT! it enables many triggers which have event a units enters region.but i checked replay and no unit entered regions and still trigger enabled.

    there are jass triggers of this spell from my map!

    Code (vJASS):

    //TESH.scrollpos=0
    //TESH.alwaysfold=0
    // *******************************************************************************
    //                          Spell: Max Bash by Dark Dragon
    //
    //                 Credits: IceFrog    -> Used in Dota! Idea is by someone...
    //                          Venom      -> Icon
    //                          nerovesper -> Request
    //
    //
    //                              Installation:
    //
    //  1. Copy 'DD Library' and this trigger to your map
    //  2. Copy abilitie and buff 'Max Bash' to your map
    //  3. Export and import "DDSpells\MaxBashHit.mdx" and icons with same path to your map if you are going to use them
    //  4. Modifie data below to mach your map and other constants
    //
    // * Enjoy!
    // *******************************************************************************






    //! zinc
    // *** This is the max bash spell library ***
    library MaxBash requires DDLib
    {
        // ======================================================================
        //                    *** Editable constants ***
        // ======================================================================
     
        // -------------------------------------------------------
        // This is the raw code of max bash ability
        // Default: 'MBsh'
        constant integer        MAX_BASH_ID                        = 'MBsh';
     
        // -------------------------------------------------------
        // This is the raw code of max bash buff
        // Default: 'MBed'
        constant integer        MAX_BASH_BUFF_ID                = 'MBed';
     
        // ----------------------------------------------------------
        // Push model file effect
        // Default: Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl
        constant string         PUSH_MODEL_FILE                  = "Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl";
     
        // ----------------------------------------------------------
        // Push model file effect of sliding unit, attach point
        // Default: foot
        constant string            PUSH_EFFECT_ATT_POINT            = "foot";
     
        // ----------------------------------------------------------
        // If custom water effect is wanted set this to true
        // Default: true
        constant boolean        USE_WATER_FILE                    = true;
     
        // ----------------------------------------------------------
        // Push model file effect on water
        // Default: Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl
        constant string            PUSH_MODEL_WATER_FILE            = "Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl";
     
        // -------------------------------------------------------
        // On push file (when ability is triggerd) applay this effect
        // Default: DDSpells\\MaxBashHit.mdx
        constant string         ON_PUSH_FILE                    = "DDSpells\\MaxBashHit.mdx";
     
        // -------------------------------------------------------
        // How often to create "PUSH_MODEL_FILE" effect
        // Default: .1
        constant real            PUSH_EFFECT_INTERVAL            = .15;
     
        // -------------------------------------------------------
        // On which point of attacker "ON_PUSH_FILE" is added?
        // Default: weapon
        constant string         ATTACH_POINT                    = "weapon";
     
        // -------------------------------------------------------
        // Effect generated on target unit when its hit
        // Default: none
        constant string         BASH_HIT_EFFECT_FILE            = "";
        constant string            BASH_HIT_EFFECT_FILE_ATT_POINT    = "origin";
     
        // -------------------------------------------------------
        // Effect generated when unit hits the ground
        // Default: Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl
        constant string         BASH_HIT_GROUND_EFFECT_FILE        = "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl";
     
        // -------------------------------------------------------
        // Effect generated when unit hits/impacts the water, requires USE_WATER_FILE to be true
        // Default: Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl
        constant string            BASH_IMPACT_WATER_EFFECT_FILE    = "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl";
     
        // -------------------------------------------------------
        // While unit is sliding, what will be its animation speed in percentage
        // Default: 65.
        constant real            UNIT_ANIM_SPEED                    = 65.;
     
        // -------------------------------------------------------
        // While unit is sliding, what will be its animation
        // Default: attack
        constant string            UNIT_ANIM_NAME                    = "death";
     
        // -------------------------------------------------------
        // Extra damage that bash deals seted up by level "function BashDamage" will
        // be treated as extra/bonus damage or as percentage of dealt damage,
        // if true percent damage will be dealt
        // Default: true
        constant boolean        BASH_DAMAGE_AS_PERCENTAGE        = true;
     
        // -------------------------------------------------------
        // This is speed in game coordinates, of how fast unit is pushed away
        // defined start and end speeds of pushed unit
        // start speed = initial speed, end speed = speed before stopping
        // Default: 350 / 50
        constant real           PUSH_SPEED_START                  = 200.;
        constant real           PUSH_SPEED_END                    = 50.;
     
        // -------------------------------------------------------
        // Enemy units that collide with sliding unit will be slightly pushed too?
        // Default: true
        constant boolean        ENABLE_SPLASH_BASH                = false;
     
        // -------------------------------------------------------
        // Damage splashed on extra colliding units in percentage
        // Default: 30%
        constant real            SPLASH_DAMAGE_PERCENTAGE        = 30.;
     
        // -------------------------------------------------------
        // The min speed at which sliding unit has to be to cause pushing other unit
        // Default: 175.
        constant real            SPLASH_BASH_NEED_SPEED            = 100.;
     
        // -------------------------------------------------------
        // The area/radius around sliding unit to check for splash damage
        // Default: 120.
        constant real            SPLASH_BASH_SCAN_R                = 120.;
     
        // -------------------------------------------------------
        // How often to check for splash bash damage
        // Default: .2
        constant real            SPLASH_BASH_INTERVAL            = .2;
     
        // -------------------------------------------------------
        // Some units have default ground offset height, what is that max height
        // so that bash does treat this units as grounded
        // Default: 50.
        constant real            SPLASH_BASH_MAX_HEIGHT            = 50.;
     
        // -------------------------------------------------------
        // Should trees be destroyed?
        // Default: true
        constant boolean        DESTROY_TREES                      = false;
     
        // -------------------------------------------------------
        // How often to clear trees
        // Default: .2
        constant real            CLEAR_TREES_INTERVAL            = .2;
     
        // -------------------------------------------------------
        // Range in which to clear trees
        // Default: 160.
        constant real            CLEAR_TREES_RADIUS                = 160.;
     
        // -------------------------------------------------------
        // Range at which to check if pathing is unpathable, for bounce code to be triggerd
        // Default: 60.
        constant real            BOUNCE_DETECT_RANGE                = 60.;
     
        // -------------------------------------------------------
        // Should floating text be created?
        // Default: true
        constant boolean        ALLOW_FLOATING_TEXT                = false;
     
        // -------------------------------------------------------
        // When units are killed by bash display KO or damage dealt
        // Default: true
        constant boolean        USE_KO_TEXT                        = true;
     
        // -------------------------------------------------------
        // The duration of floating text in seconds
        // Default: 4.25
        constant real           FLOATING_TEXT_DURATION             = 3.;
     
        // -------------------------------------------------------
        // The color of text rgb transparency in percentage
        // Default: 100. / 100. / 100. / 20.
        constant real            FLOATING_TEXT_RED                = 100.;
        constant real            FLOATING_TEXT_GREEN                = 100.;
        constant real            FLOATING_TEXT_BLUE                = 100.;
        constant real            FLOATING_TEXT_TRANS                = 20.;
     
        // -------------------------------------------------------------
        constant key            UNIT_BASH_KEY;
        // -------------------------------------------------------------
        //          *** Level data setup here ***
     
     
        // -------------------------------------------
        // *** The bash damage per level ***
        // Default: 2.6 / 3.4 / 4.5
        function BashDamage(integer level) -> real {
            real bash_damage[];
         
            bash_damage[1] = 0.0;
            bash_damage[2] = 0.0;
            bash_damage[3] = 0.0;
         
            return bash_damage[level];
        }
     
        // -------------------------------------------
        // *** The bash push distance per level ***
        // Default: 300. / 300. / 300.
        function BashPushDistance(integer level) -> real {
            real bash_range[];
         
            bash_range[1] = 230.;
            bash_range[2] = 350.;
            bash_range[3] = 200.;
         
            return bash_range[level];
        }
     
        // -------------------------------------------
        // *** The bash push height per level ***
        // Default: 150. / 150. / 150.
        function BashPushHeight(integer level) -> real {
            real bash_height[];
         
            bash_height[1] = 150.;
            bash_height[2] = 150.;
            bash_height[3] = 150.;
         
            return bash_height[level];
        }
     
        // -------------------------------------------
        // *** The bash push height travel percentage per level ***
        // This setting says at which percentage of path will unit land
        // Default: 40. / 40. / 40.
        function BashPushHeightTravelPerc(integer level) -> real {
            real bash_height_travel_perc[];
         
            bash_height_travel_perc[1] = 40.;
            bash_height_travel_perc[2] = 40.;
            bash_height_travel_perc[3] = 40.;
         
            return bash_height_travel_perc[level];
        }
     
        // -------------------------------------------
        // *** The damaged dealt by impact
        // Default: 50. / 50. / 50.
        function BashPushGroundImpactDamage(integer level) -> real {
            real bash_ground_impact_damage[];
         
            bash_ground_impact_damage[1] = 120.;
            bash_ground_impact_damage[2] = 300.;
            bash_ground_impact_damage[3] = 120.;
         
            return bash_ground_impact_damage[level];
        }
     
     
        // -------------------------------------------
        // *** If splash bash is activated, this will filter which are proper units to be pushed.
        function SplashBashFilter(unit filter_unit, player bashPlayer) -> boolean {
            return  !IsUnitType(filter_unit, UNIT_TYPE_DEAD)                         &&
                    IsUnitEnemy(filter_unit, bashPlayer)                             &&
                    IsUnitType(filter_unit, UNIT_TYPE_GROUND)                        &&
                    !BlzIsUnitInvulnerable(filter_unit)                                &&
                    !IsUnitType(filter_unit, UNIT_TYPE_STRUCTURE)                    &&
                    !DDIsUnitWard(filter_unit);
        }
     
        // ==================================================================================
        //                         *** End spell modification ***
        // ==================================================================================
     
        // ---------------------------------------------------------
        // *** Bash data structure
        struct bash {
            private {
                unit         b, s;
                real         dist, mxdist, impdist;
                real         dx, dy, initZ;
                p_real        z_parab;
                real        dmg;
                p_real         vec;
                integer     p, lvl;
                boolean        hit_ground;
            }
         
            /// ----------------------------------------------------------------
         
            // ***
            static method create(integer castplayer, unit bashingUnit, unit whichUnit, integer lvl, real distance, real radians, real damage) -> bash {
                bash this = allocate();
             
                s             = bashingUnit;
                b             = whichUnit;
                dist         = distance;
                mxdist        = SquareRoot(distance);
                dx            = Cos(radians);
                dy            = Sin(radians);
                vec            = pVector(GetUnitX(b), GetUnitY(b), GetUnitFlyHeight(b));
                p            = castplayer;
                dmg            = damage;
                hit_ground     = BashPushGroundImpactDamage(lvl) < 1.;
             
                // -------------------------
                // a(x-x0)^2 + y0 = a(x^2 - 2x*x0 + x0^2) + y0 = a*(x)^2 - 2*a*x0*(x) + a*x0^2+y0
                // -------------------------
                // x0 = mxDist(100-perc/2)/100
                // y0 = vec[2] + h
                // a = -h / (mtd/2)^2
                // b = -2*a*x0
                // c = y0+a*x0^2
                z_parab     = p_real.create();
                z_parab[0]     = -BashPushHeight(lvl) / Pw_2(BashPushHeightTravelPerc(lvl)*distance/200.);         // a = -h / (mtd/2)^2
                z_parab[1]     = -2. * z_parab[0] * ((100.-BashPushHeightTravelPerc(lvl)/2.)*distance/100.);                                                 // b = -2*a*x0
                z_parab[2]     = (BashPushHeight(lvl) + vec[2]) + z_parab[0]*Pw_2((100.-BashPushHeightTravelPerc(lvl)/2.)*distance/100.);                 // c = a*x0^2+y0
                this.lvl     = lvl;
                impdist        = (100.-BashPushHeightTravelPerc(lvl))*distance/100.;
                initZ        = vec[2];
             
                DDSet(b, UNIT_BASH_KEY, this);
                UnitAddAbility(b, 'Amrf');
                UnitRemoveAbility(b, 'Amrf');
                SetUnitTimeScale(b, UNIT_ANIM_SPEED*.01);
                if (!IsUnitType(b, UNIT_TYPE_DEAD)) {
                    SetUnitAnimation(b, UNIT_ANIM_NAME);
                    QueueUnitAnimation(b, "stand");
                }
             
                return this;
            }
         
            // ***
            method destroy() {
                DDSet(b, UNIT_BASH_KEY, p_null);
                SetUnitTimeScale(b, 1.);
                vec.destroy();
                z_parab.destroy();
                s = null;
                b = null;
                deallocate();
            }
         
            method operator IsAirborn() -> boolean { return !hit_ground; }
         
            /// ----------------------------------------------------------------
            //* splash code
            private method TryDoSplashBash() {
                integer i;
                unit u;
             
                // *** Skip splash if unit is in air ***
                if (vec[2] > SPLASH_BASH_MAX_HEIGHT)
                    return;
             
                // --------------------------------------
                // *** pick units to be splash bashed
                DDGroupFillMemArea(vec[0], vec[1], SPLASH_BASH_SCAN_R, p, function() -> boolean {
                    return SplashBashFilter(GetFilterUnit(), Player(DDMemUnitData())) && DDGet(GetFilterUnit(), UNIT_BASH_KEY) == p_null;
                });
             
                // --------------------------------------------------------------
                // *** Now launch them in there respective directions and speeds
                for(i=0; i < DDMemUnitN(); i+=1) {
                    u = DDMemUnit(i);
                 
                    // *** Do damage and bash the target ***
                    UnitDamageTarget(s, u, dmg*SPLASH_DAMAGE_PERCENTAGE*.01, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS);
                    BashExecute.evaluate(p, s, u, lvl, dist, Atan2(GetUnitY(u)-vec[1], GetUnitX(u)-vec[0]), dmg);
                 
                    // *** Floating text add? ***
                    static if (ALLOW_FLOATING_TEXT)
                        static if (USE_KO_TEXT)
                            if (IsUnitType(u, UNIT_TYPE_DEAD))
                                DDNewTextTagUnit(u, "|cffff0000KO!!!|r", FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
                            else
                                DDNewTextTagUnit(u, "+"+I2S(R2I(dmg*SPLASH_DAMAGE_PERCENTAGE*.01)), FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
                        else
                            DDNewTextTagUnit(u, "+"+I2S(R2I(dmg*SPLASH_DAMAGE_PERCENTAGE*.01)), FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
                }
             
            }
         
            // -------------------------------------------------------------------------
            // * checks and performs ground impact as well as dealing damage and displaying floating text
            method CheckGroundHit() {
                if (impdist > dist) {
                    vec[2] = initZ;
                    if (!hit_ground) {
                        hit_ground = true;
                        static if (USE_WATER_FILE)
                            if (IsTerrainPathable(vec[0], vec[1], PATHING_TYPE_FLOATABILITY))
                                DestroyEffect(AddSpecialEffect(BASH_HIT_GROUND_EFFECT_FILE, vec[0], vec[1]));
                            else
                                DestroyEffect(AddSpecialEffect(BASH_IMPACT_WATER_EFFECT_FILE, vec[0], vec[1]));
                        else
                            DestroyEffect(AddSpecialEffect(BASH_HIT_GROUND_EFFECT_FILE, vec[0], vec[1]));
                     
                        if (!IsUnitType(b, UNIT_TYPE_DEAD)) {
                            UnitDamageTarget(s, b, BashPushGroundImpactDamage(lvl), true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS);
                            // *** Floating text add? ***
                            static if (ALLOW_FLOATING_TEXT)
                                static if (USE_KO_TEXT)
                                    if (IsUnitType(b, UNIT_TYPE_DEAD))
                                        DDNewTextTagUnit(b, "|cffff0000KO!!!|r", FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
                                    else
                                        DDNewTextTagUnit(b, "+"+I2S(R2I(BashPushGroundImpactDamage(lvl))), FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
                                else
                                    DDNewTextTagUnit(b, "+"+I2S(R2I(BashPushGroundImpactDamage(lvl))), FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
                        }
                    }
                }
            }
         
            /// ----------------------------------------------------------------
            //* primary push code
            method Launch() {
                DDStartTim(DD_INTERVAL, true, this, static method() {
                    bash         this         = bash( DDTimData() );
                    integer     tick        = DDTimTick();
                    real         speed         = DD_INTERVAL * (PUSH_SPEED_END + ( (PUSH_SPEED_START-PUSH_SPEED_END)/mxdist )*SquareRoot(dist));
                    // basic formula for speed: y = a*sqrt(x) + b
                 
                    // ----------------------------------
                    // *** Position calcs
                    dist     -= speed;
                    vec[0]    += speed * dx;
                    vec[1]    += speed * dy;
                    vec[2]     = (z_parab[0]*Pw_2(dist)) + (z_parab[1]*dist) + (z_parab[2]);
                 
                    // ------------------------------------
                    // *** Check if hit ground ***
                    CheckGroundHit();
                 
                    // ----------------------------------
                    // *** Motion
                    SetUnitX(b, vec[0]);
                    SetUnitY(b, vec[1]);
                    SetUnitFlyHeight(b, vec[2], 0.);
                 
                    // ----------------------------------
                    // *** Push Effects
                    if (ModuloReal(tick*DD_INTERVAL, PUSH_EFFECT_INTERVAL) < DD_INTERVAL)
                        static if (USE_WATER_FILE)
                            if (IsTerrainPathable(vec[0], vec[1], PATHING_TYPE_FLOATABILITY) || vec[2] > SPLASH_BASH_MAX_HEIGHT)
                                DestroyEffect(AddSpecialEffectTarget(PUSH_MODEL_FILE, b, PUSH_EFFECT_ATT_POINT));
                            else
                                DestroyEffect(AddSpecialEffectTarget(PUSH_MODEL_WATER_FILE, b, PUSH_EFFECT_ATT_POINT));
                        else
                            DestroyEffect(AddSpecialEffectTarget(PUSH_MODEL_FILE, b, PUSH_EFFECT_ATT_POINT));
                 
                    // ----------------------------------------
                    // *** Check if trees are in the way
                    static if (DESTROY_TREES)
                        if (ModuloReal(tick*DD_INTERVAL, CLEAR_TREES_INTERVAL) < DD_INTERVAL) {
                         
                            DDEnumDestsInRange(vec, CLEAR_TREES_RADIUS, null, function() {
                                if (DDIsDestructableTree(GetEnumDestructable()))
                                    KillDestructable(GetEnumDestructable());
                            });
                        }
                 
                    // ---------------------------------------------------------
                    // *** Check for bounce/collision with unpathable points
                    if (ModuloReal(tick*DD_INTERVAL, CLEAR_TREES_INTERVAL) < DD_INTERVAL) {
                        if (IsTerrainPathable(vec[0]+BOUNCE_DETECT_RANGE*dx, vec[1], PATHING_TYPE_WALKABILITY))
                            dx = -dx;
                        else if (IsTerrainPathable(vec[0], vec[1]+BOUNCE_DETECT_RANGE*dy, PATHING_TYPE_WALKABILITY))
                            dy = -dy;
                    }
                 
                    // ----------------------------------------
                    // *** Check if there are any units to be splash bashed
                    static if (ENABLE_SPLASH_BASH)
                        if (speed > SPLASH_BASH_NEED_SPEED*DD_INTERVAL && ModuloReal(tick*DD_INTERVAL, SPLASH_BASH_INTERVAL) < DD_INTERVAL)
                            TryDoSplashBash();
                     
                    // ----------------------------------
                    // *** Check to quit push
                    if (dist <= 0.) {
                        PauseUnit(b, false);
                        destroy();
                        DDQuitTim();
                    }
                });
            }
        }
     
        // *** Bash function that will be called from above and below
        function BashExecute(integer p, unit basher, unit u, integer lvl, real dist, real radians, real dmg) {
            // *** Now pause the victim ***
            PauseUnit(u, true);
            DestroyEffect(AddSpecialEffectTarget(BASH_HIT_EFFECT_FILE, u, BASH_HIT_EFFECT_FILE_ATT_POINT));
            bash.create(p, basher, u, lvl, dist, radians, dmg).Launch(); /// *** Will be auto destroyed
        }
     
        // ==================================================================================
        //                             *** Initialization ***
        function onInit() {
            trigger t = CreateTrigger();
         
            TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED);
            DDTriggerRegisterAnyUnitDamaged(t);
            TriggerAddCondition(t, function() -> boolean {
                unit          u;
                unit          v;
                integer      lvl;
                real        dmg    = 0.;
                bash        b;
             
                // *** Attac
                if (GetTriggerEventId() == EVENT_PLAYER_UNIT_ATTACKED) {
                    u = GetAttacker();
                    v = GetTriggerUnit();
                    b = DDGet(v, UNIT_BASH_KEY);
                 
                    if (b != p_null)
                        if (IsUnitType(u, UNIT_TYPE_MELEE_ATTACKER) && b.IsAirborn)
                            IssueImmediateOrder(u, "stop");
                 
                    u = null;
                    v = null;
                    return false;
                }
             
                u       = GetEventDamageSource();                    // Damages source unit
                v       = GetTriggerUnit();                          // Victim unit
                lvl     = GetUnitAbilityLevel(u, MAX_BASH_ID);      // Spell level
             
             
                // --------------------------------------
                // *** Condition
                if (GetUnitAbilityLevel(v, MAX_BASH_BUFF_ID) == 0 || DDGet(v, UNIT_BASH_KEY) != p_null) {
                    UnitRemoveAbility(v, MAX_BASH_BUFF_ID);
                    u = null;
                    v = null;
                    return false;
                }
             
                // *** No future exec, prevent exec this trigger when we call "UnitDamageTarget" below ***
                DisableTrigger(GetTriggeringTrigger());
             
                // *** Clear the buff ***
                UnitRemoveAbility(v, MAX_BASH_BUFF_ID);
             
                // *** Primary damage ***
                static if (BASH_DAMAGE_AS_PERCENTAGE)
                    dmg = GetEventDamage()*BashDamage(lvl);
                else
                    dmg = BashDamage(lvl);
             
                BlzSetEventDamage(GetEventDamage() + dmg);
                //UnitDamageTarget(u, v, dmg, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS);

                // *** Apply custom effect ***
                DestroyEffect(AddSpecialEffectTarget(ON_PUSH_FILE, u, ATTACH_POINT));

                // *** Floating text add? ***
                static if (ALLOW_FLOATING_TEXT)
                    static if (USE_KO_TEXT)
                        if (IsUnitType(v, UNIT_TYPE_DEAD))
                            DDNewTextTagUnit(v, "|cffff0000KO!!!|r", FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
                        else
                            DDNewTextTagUnit(v, "+"+I2S(R2I(dmg)), FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
                    else
                        DDNewTextTagUnit(v, "+"+I2S(R2I(dmg)), FLOATING_TEXT_DURATION, FLOATING_TEXT_RED, FLOATING_TEXT_GREEN, FLOATING_TEXT_BLUE, FLOATING_TEXT_TRANS);
                     
             
                // *** Load main bash struct ***
                BashExecute(GetPlayerId(GetOwningPlayer(u)), u, v, lvl, BashPushDistance(lvl), Atan2(GetUnitY(v)-GetUnitY(u), GetUnitX(v)-GetUnitX(u)), dmg);

                // *** Allow next exec ***
                EnableTrigger(GetTriggeringTrigger());
         
                // *** Null locals ***
                u = null;
                v = null;
                return false;
            });
        }
    }
    //! 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 MAX_BASH_ABIL_ID                    = "MBsh"
        //! i MAX_BASH_BUFF_ID                    = "MBed"
     
        //! i -- =================================================================

         //! i setobjecttype("buffs")
         //! i createobject("BSTN", MAX_BASH_BUFF_ID)
         //! i makechange(current, "fart", "ReplaceableTextures\\CommandButtons\\PASBash.blp")
         //! i makechange(current, "ftat", "")
         //! i makechange(current, "fta0", "")
         //! i makechange(current, "fnam", "Max Bash")
         //! i makechange(current, "ftip", "Max Bash")
     
         //! i setobjecttype("abilities")
         //! i createobject("AHbh", MAX_BASH_ABIL_ID)
         //! i makechange(current,"anam", "Max Bash")
         //! i makechange(current,"aart", "ReplaceableTextures\\CommandButtons\\PASBash.blp")
         //! i makechange(current,"arar", "ReplaceableTextures\\CommandButtons\\PASBash.blp")
         //! i makechange(current,"abpx", "3")
         //! i makechange(current,"arpx", "3")
         //! i -- makechange(current,"alev", "3")
         //! i -- makechange(current,"arlv", "1")
         //! i -- makechange(current,"ahky", "H")
         //! i makechange(current,"arhk", "X")
         //! i makechange(current,"aret", "Learn Ma|cff109da9x|r Bash - [|cffffcc00Level ".. string.char(37) .."d|r]")
         //! i makechange(current,"arut", "|cffc0c0c0Gives a percent chance to deal extra damage and push target. Sliding unit deals splash bash that slightly pushes units and deals 30% damage from original bash. |r|n|n|cffffcc00Level 1|r - 15% chance, 2.6x damage, 200 distance push. |n|cffffcc00Level 2|r - 17% chance, 3.4x damage, 230 distance push. |n|cffffcc00Level 3|r - 20% chance, 4.5x damage, 270 distance push.")
         //! i makechange(current,"aub1","1","|cffc0c0c0Gives a 15% chance to deal extra 2.6x damage, push target 200 offset distance and deal 30% splash bash.|r")
         //! i makechange(current,"aub1","2","|cffc0c0c0Gives a 17% chance to deal extra 3.4x damage, push target 230 offset distance and deal 30% splash bash.|r")
         //! i makechange(current,"aub1","3","|cffc0c0c0Gives a 20% chance to deal extra 4.5x damage, push target 270 offset distance and deal 30% splash bash.|r")
       
         //! i local i = 0
         //! i for i=1, 3 do
            //! i local si = tostring(i)
            //! i makechange(current,"atar",si,"Enemy,Ground,Organic")
            //! i -- makechange(current,"aran",si,"99999.")
            //! i makechange(current,"Hbh1",si,tostring(13+(2*i)))
            //! i makechange(current,"abuf",si,"MBed")
            //! i makechange(current,"Hbh5",si,"1")
            //! i makechange(current,"Hbh3",si,"0.")
            //! i makechange(current,"atp1",si,"Max Bash - [|cffffcc00Level ".. si .."|r]")
         //! i end
         //! i makechange(current,"Hbh1","3","20.")
    //! endexternalblock

           */

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


     






    Code (vJASS):

    //==========================================================================
    //                  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











     
     
  13. emil23

    emil23

    Joined:
    Jul 17, 2013
    Messages:
    222
    Resources:
    1
    Maps:
    1
    Resources:
    1
  14. Dark_Dragon

    Dark_Dragon

    Joined:
    Jul 19, 2007
    Messages:
    596
    Resources:
    8
    Tools:
    1
    Spells:
    7
    Resources:
    8
    Hi,

    1) are there any triggers in your map which run at exactlly 20 minutes after game starts?
    if so can you check them or post them here?

    2) You need dummy unit in the map because dummy is used to check if destructable is tree, since you set 'DESTROY_TREES' to false, you dont need dummy for this spell.

    3) This spell is made on WC3 1.30.4 patch, which WC3 version do you use?

    The code in between /* */ should not be used!

    Regards!
    ~DD
     
    Last edited: Sep 2, 2019
  15. emil23

    emil23

    Joined:
    Jul 17, 2013
    Messages:
    222
    Resources:
    1
    Maps:
    1
    Resources:
    1
    Sorry for being such desperated but i love this system so much and i am sad this wont work. well i also copied unit named dumy from object editor is this what you mean? i just didnt see model mdx with dummy to import

    Well sadly no :( there are only triggers which works every minute. they check if anyone left game and if it should share leavers gold to allies.I have removed them and some other custom spells im using im gonna test now.

    If you want i can send you my map so you can check it out better as i have no idea what can cause it maybe im just nub and i installed it wrongly.In read me there was also said to copy unit chill ability but what it means? there was only max bash ability to copy.
     
  16. Dark_Dragon

    Dark_Dragon

    Joined:
    Jul 19, 2007
    Messages:
    596
    Resources:
    8
    Tools:
    1
    Spells:
    7
    Resources:
    8
    Ok, you can upload to 'Pastebin' your map and send me the link.
    Regards!
    ~DD
     
  17. emil23

    emil23

    Joined:
    Jul 17, 2013
    Messages:
    222
    Resources:
    1
    Maps:
    1
    Resources:
    1
    i send u private message so no one else can dl map. is it fine if i uploaded to other webside? i find pastebin bit wierd i didnt see option to upload file just text.
     
  18. Dark_Dragon

    Dark_Dragon

    Joined:
    Jul 19, 2007
    Messages:
    596
    Resources:
    8
    Tools:
    1
    Spells:
    7
    Resources:
    8
    Hi,

    i downloaded the map, but i cant open it!
    https://www.hiveworkshop.com/attachments/clipboard01-jpg.332023/

    the reason might be that it uses different WC3 version, my is v1.30.4

    it is true that dummy model is missing from import manager, i am going to fix that!

    It could be that timers running every minute, after 20 executions do something...

    Regards!
    ~DD
     
  19. emil23

    emil23

    Joined:
    Jul 17, 2013
    Messages:
    222
    Resources:
    1
    Maps:
    1
    Resources:
    1
    well yes i use latest patch 1.31. anyway way to fix it then?
     
  20. Dark_Dragon

    Dark_Dragon

    Joined:
    Jul 19, 2007
    Messages:
    596
    Resources:
    8
    Tools:
    1
    Spells:
    7
    Resources:
    8
    Unless it is timers running every minute, after 20 executions i would not know due to high complexity of the map and new patch.

    Regards!
    ~DD