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. 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
  5. The 18th Icon Contest is ON! Choose any ingame unit and give him/her Hero abilities. Good luck to all.
    Dismiss Notice
  6. The Secrets of Warcraft 3 have revealed interesting works. The RESULTS for Abelhawk's Mini-Mapping Contest #15 have come out!
    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. Night Rider gained several songs for his journey. The poll for the 12th Music Contest has started. Check it out!
    Dismiss Notice
  10. 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
  11. 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. 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 very familiar with it.
    2. You should place your trigger in the globals block. It is currently not private. On that note, you shouldn't be using the default name, either.
    3. You should be using functions instead of arrays for configuration (more of a personal preference).
    4. Personally, I find the entire way your system is setup unnecessarily overcomplicated, with custom functions only calling a single function themselves. I suggest taking a look at Silvenon's knockback system to see how you could make easy improvements.

    Tha quality is acceptable, but I'd like you to keep improving this.
     
  2. Elsheen

    Elsheen

    Joined:
    Mar 5, 2009
    Messages:
    136
    Resources:
    0
    Resources:
    0
    I dont really see why this needs to be in vJASS, but I think it would be much more simpler to just use a GUI/Trigger knockback system and use a critical strike passive.
     
  3. Dark_Dragon

    Dark_Dragon

    Joined:
    Jul 19, 2007
    Messages:
    591
    Resources:
    8
    Tools:
    1
    Spells:
    7
    Resources:
    8
    ty for ur comment!
    however its not that simple as you think it is ;)
     
  4. Elsheen

    Elsheen

    Joined:
    Mar 5, 2009
    Messages:
    136
    Resources:
    0
    Resources:
    0
    Your warm reaction makes me feel all fuzzy inside =) Btw, I didnt say how I feel about it, I think its a nice spell ;)
     
  5. Deuterium

    Deuterium

    Joined:
    Mar 17, 2009
    Messages:
    1,301
    Resources:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    2
    It's all about the efficiency :p + user-friendliness + easier to work with if you know Jass


    @ Dark_Dragon:
    Nice use of trigonometry :p However, I've got a question:
    I've seen you used four BJ's in your script, couldn't those be avoidable? I mean I don't know about RMaxBJ and RMinBJ, but I've notice that SetTextTagVelocityBJ has a native SetTextTagVelocity...

    Works as it should and the knockback is nice and smooth.

    Good job DD!
     
  6. Deaod

    Deaod

    Joined:
    Nov 18, 2007
    Messages:
    804
    Resources:
    12
    Maps:
    1
    Spells:
    11
    Resources:
    12
    I could have done this with 8 libraries in less than 75 lines. Interested?
    You do know the point of libraries is to actually USE them, dont you?

    Edit: I suppose using a Critical Strike based ability may acutally reduce the number of used libraries by 5 (while still providing nearly the exact same behaviour).
     
  7. thereallywhitekid

    thereallywhitekid

    Joined:
    Nov 18, 2008
    Messages:
    115
    Resources:
    0
    Resources:
    0
    Since this is from DotA, I am guessing that this is Barathrum's "Greater Bash" Skill right?
    Anyways, Barathrum's greater bash is just a passive knockback with a greater distance per level and more damage. It's actually easy to make this in GUI. The only hard part about it is the distance change per level.
    Just read this link: http://forums.dota-allstars.com/index.php?showtopic=220166

    That's how I made mine but it's in GUI and doesn't have the distance change. (It can be solved but I'm just too lazy to do it)

    Try making Leviathan's Ravage Spell in vJass. I already made one in GUI and submitted it. (But no one downloaded it :cry:)
     
  8. Dark_Dragon

    Dark_Dragon

    Joined:
    Jul 19, 2007
    Messages:
    591
    Resources:
    8
    Tools:
    1
    Spells:
    7
    Resources:
    8
    thanks thats why i made it ;)

    ohh yeah xD RMin and RMax are actually short functions which just return which of this numbers are bigger or smaller. so the reason why i used them is coz i dont know what will user setup in script above (example:) in current script START_SPEED > END_SPEED so it is something like defaults and i dont need that RMinBJ. however if user makes END_SPEED > START_SPEED (well duno xD maybe someone will) and if he does i dont want my spell to bug ;) so thats why i used that if then else with Min, Max BJ-s

    ofc i used them coz i know how coded they are, and they do not leak. well they will waste few nanoseconds like any other function or method call ;)

    About texttag well i just wanted to simple use that bj_lastCretedTextTag. and ofc none of this functions are single lined (thats why i used them).

    note as well that all of this BJ-s Inside are supposed to be inlined by JH

    Code (vJASS):

    function CreateTextTagUnitBJ takes string s, unit whichUnit, real zOffset, real size, real red, real green, real blue, real transparency returns texttag
        set bj_lastCreatedTextTag = CreateTextTag()
        call SetTextTagTextBJ(bj_lastCreatedTextTag, s, size)
        call SetTextTagPosUnitBJ(bj_lastCreatedTextTag, whichUnit, zOffset)
        call SetTextTagColorBJ(bj_lastCreatedTextTag, red, green, blue, transparency)

        return bj_lastCreatedTextTag
    endfunction
     


    Code (vJASS):

    function SetTextTagVelocityBJ takes texttag tt, real speed, real angle returns nothing
        local real vel = TextTagSpeed2Velocity(speed)
        local real xvel = vel * Cos(angle * bj_DEGTORAD)
        local real yvel = vel * Sin(angle * bj_DEGTORAD)

        call SetTextTagVelocity(tt, xvel, yvel)
    endfunction
     


    well reason why i used it is coz i hate to use something i dont know (why does it like like it dose)! what do i mean? well that function TextTagSpeed2Velocity() is a BJ and it does some calculations i really have no idea why they look like that. its just that i am pissed when i dont know something expecially from math, physics which this 100% is :S

    anyway dont worry its just a two BJ-s called once per spell getting triggerd ;)

    thanks i am glade you like it!

    ohh y i know! well its just that during the time when i was lerining programming i always hadded to do everything myself since it was hard to find someone who could have teach me everything i wanted to know :S

    and well when i am codining in c++ the only includes i use are the one which register natives for my use... well when it comes to school and examples we all ofc use printf(const char*, ...) well its quite a long functions since it has to read all that %d, %f, %lf, %c and a lot more... so i would really not code it myself + ofc we use #include <iostream> which u know has full of stuff which is not just registering natives... cout, cin, are the most i use xD

    so i know its better not to write my own library coz it has longer code but is as well efficient as much as it could be.

    all in all ty for ur comment but i just like to code all the code myself since it my spell :S

    btw i have a question for u!
    did you try to uncomment that line which changes RandomSeed? if so then u will see quite good randomize for short amount of time and then it will start to generate only 96 and 69... omg some kinde of blizzard bug or better to say bad algorithm i guess... heh that blizz :D

    once again! everyone ty for all your feedback and greets!
    ~Dark Dragon
     
  9. Anachron

    Anachron

    Joined:
    Sep 9, 2007
    Messages:
    6,167
    Resources:
    66
    Icons:
    49
    Packs:
    2
    Tools:
    1
    Maps:
    3
    Spells:
    9
    Tutorials:
    1
    JASS:
    1
    Resources:
    66
    Actually, it wasn't IceFrogs idea. Someone other postet the hero in Hero Suggestions Thread and it got accepted. Back to topic, this spell is nice and good coded. I give it a 4/5 because this seems to be useful but its not that new.
     
  10. Dark_Dragon

    Dark_Dragon

    Joined:
    Jul 19, 2007
    Messages:
    591
    Resources:
    8
    Tools:
    1
    Spells:
    7
    Resources:
    8
    :S i did not know that! well IceFrog sure takes some spells as well, well thats fine too xD

    ofc its 4/5 spell which has not my idea in it does not worth 5/5 coz its not fully my work ;)

    and ofc it was requested thats just another reason that idea does not belong to me :D

    Greets!
    ~Dark Dragon
     
  11. Deaod

    Deaod

    Joined:
    Nov 18, 2007
    Messages:
    804
    Resources:
    12
    Maps:
    1
    Spells:
    11
    Resources:
    12
    Good c++ compilers delete code not used. And Vex's Optimizer does that as well.

    This being your spell doesnt justify anything. You can still use other peoples resources, since those are useful for many kinds of applications while your reinvented wheel being a knockback system maybe has a few features less that others will miss.

    Point is, stop reinventing the wheel over and over again. It's already been done. And while other peoples code may not be as efficient as it could be, why not optimize it yourself in your own map and let others optimize it themselves? Its better to use standard libraries than to reinvent a wheel a thousand times over and over again. It saves you development time, it avoids all kinds of bugs that are likely to occur in your code simply because they had more time to find and fix all those rare bugs. It helps developing standards for certain things, like Table or TimerUtils are now.

    Did you try and uncheck "Use fixed random seed" in one of the option panels of the world editor?
     
  12. Deuterium

    Deuterium

    Joined:
    Mar 17, 2009
    Messages:
    1,301
    Resources:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    2
    Why depend on others when you're able of doing the whole job easily yourself? :p
    If DarkDragon can easily do the whole spell without using libraries and have it as efficient as possible... then there's no reason for using them :p

    Yup he sure does. He's always mentioning in his blog how he appreciates people sending him emails containing ideas :)
     
  13. Dark_Dragon

    Dark_Dragon

    Joined:
    Jul 19, 2007
    Messages:
    591
    Resources:
    8
    Tools:
    1
    Spells:
    7
    Resources:
    8
    a well i did not mean that i have no right to use other people resources! hmm i just dont know how to explain what my problem was :S well its just that i never used anyones code coz i hadded to learn myself from the start to the end... and if i where using other people work, well simple to say i would know less then i know now.

    ofc i understand that there resources are made for me/anyone else to use them so i just need to give credits.

    :O i did not know that vexs optimizer does that! so if i make too much or better to say multiple private H2I funcs vexs optimizer removes them and use only a main one?

    well thats cool ;)

    o well i get your point and well its true that i could even optimize it as i want + it would save me time and make it more stable coz once i made an library i can always use it instead of rewriting same code hundret times. i know you are correct about this so ill see what i can do, maybe at leat write my own librarys which ill use whole the time insted of writing same thing again and again. ofc its not just the extra time i need to write all that but as well taking space in RAM for extra functions... well even if we today have about 2 GB RAM i have 1.5 GB :S anyway i still will take ur suggestion and will see what i can do ;)

    wot i never even knew about this! so i just went to check it now and y it is not enabled so it is supposed to work... but it does not, it crashes at least for me :S

    however ty for telling me abot this, did not know it exists!

    well that depends on who is writing the code and how well is it done...
    example struct.allocate() is a well coded method with fast algorithm as well as destroy method. since many people who are now programming in vjass dont even know about making some fast algorithms there is this standart. so you dont need to know everything complex by urself but you can use others people script which is faster then that autors code...

    the same goes for librarys Deaod spoke of! there are quite well coded standards already but well they are made to work with most of stuff you need. however even that sometimes is not enough so you still need to code some stuff urself... the good thing is that it saves ur time, decreases lines of code and simple does not require you to register new functions again. so this is quite good but speed might be only a little slower for example:

    Code (vJASS):

    // My
    constant function QMod takes integer a, integer b returns integer
        return a - (a/b) * b
    endfunction

    // Blizzard
    function ModuloInteger takes integer a, integer b returns integer
        local integer mod = a - (a/b) * b
        if (mod < 0) then
            set mod = mod + b
        endif
        return mod
    endfunction
     


    blizzards one works for any inputed numbers but my works only for positive ones. and thats enough for me in this spell so i made it faster which matches my spell.

    the same goes for other people librarys they must make all there stuff work in any situation, which makes it a bit slower... but still all other things like time and rewriting bla bla is as well important... so its the reason i dont know which one to choose xD

    well i never talked to him or posted anything in forums...
    the only thing i did for dota is reported bug with razors ultimate not changing damage per level until he dies or gets stunned...

    ofc i posted in that suggestion like Multi Kill rather then just playing tripple kill even if u kill more then 3 but he never gave replay nor anything else... since he saw in that map that i was a GUI noob... triggers full of leaks non-MUI stuff... so he just took my bug report and nothing else... well thats fine with me xD

    Greets!
    ~Dark Dragon
     
  14. Deaod

    Deaod

    Joined:
    Nov 18, 2007
    Messages:
    804
    Resources:
    12
    Maps:
    1
    Spells:
    11
    Resources:
    12
    Deuterium, read the rest of my post. I could reinvent the wheel a thousand times over and over again. I could make each spell of mine include a group and timer recycling system. But after a few times of implementing all that crap you get tired of it. So you just reuse code you wrote before, this allows you to use that time you previously needed to implement the recycling to code new, creative things.

    Dark_Dragon, seems like i didnt express myself correctly. The optimizer does not delete functions that are referenced later in the map script, it only deletes completely unused functions that are never called or executed. It also wont merge multiple instances of the H2I function.

    WC3 typically uses ~90 MB of RAM. WC3 will be completely unusable long before you get anywhere near 1.5 GB of used RAM.
     
  15. Deuterium

    Deuterium

    Joined:
    Mar 17, 2009
    Messages:
    1,301
    Resources:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    2
    off-topic:
    I've seen say these things more then once, so thought you'd like to know that what ur saying is wrong literaly...
    The past tense of have is had not hadded.
    It's reply and not replay...
    replay is when you re-watch a movie or re-listen to a song - basically playing something again: re-play :p

    This bug must have been before i even knew warcraft existed... and i cant imagine any situation in which you could possibly have noticed that bug :p
     
  16. Dark_Dragon

    Dark_Dragon

    Joined:
    Jul 19, 2007
    Messages:
    591
    Resources:
    8
    Tools:
    1
    Spells:
    7
    Resources:
    8
    ahh soo... sry i got confused for a sec yy u explained it well its just me who got it wrong. well optimizer removes only funcs which are never called xD

    o yeah well i actually did not even think about using 1.5 GB! i only thought that well for each function it has to use some small amount of RAM but i dont think i would break the limits :D

    Anyway thanks for explaining things +rep!

    ahh thanks for telling me about this mistakes, ill make sure not to write that bad ;)

    ahh you are right that was an hard bug to find and it existed from beginning...
    well i cant remember correctly but i know that i found it out when i was making my own ability from passive immolation. then it did not work when i level up, but when i died it was again fine :S so i checked it in dota and saw that this bugs there as well xD

    greets and will give u rep when i can ;)
    ~Dark Dragon
     
  17. -Berz-

    -Berz-

    Joined:
    Mar 5, 2008
    Messages:
    3,203
    Resources:
    123
    Icons:
    111
    Packs:
    1
    Skins:
    1
    Spells:
    10
    Resources:
    123
    Nice, i just love when you get lucky enough to "cast" it twice in a row ;D

    It's a useful spell for any kind of maps.

    Try to add some more epic special effects =)
     
  18. Dark_Dragon

    Dark_Dragon

    Joined:
    Jul 19, 2007
    Messages:
    591
    Resources:
    8
    Tools:
    1
    Spells:
    7
    Resources:
    8
    ty for comment xD!

    well i was requested to do it like this but i could add maybe some extra special effects for user setup.

    will see about that ;)

    Greets!
    ~Dark Dragon
     
  19. nerovesper

    nerovesper

    Joined:
    Sep 29, 2008
    Messages:
    614
    Resources:
    2
    Maps:
    1
    Spells:
    1
    Resources:
    2
    Thanks once again DD, for making my request. xD