• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Release of energy

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
JASS:
scope Grenadle initializer Init
   globals
      private constant integer AbilityID = 'A002'
      private constant integer DummyID   = 'hfoo'
   endglobals
 
native UnitAlive takes unit id returns boolean

private function AngleBetweenPointsXY takes real x1, real y1, real x2, real y2 returns real
    return bj_RADTODEG * Atan2(x1 - y1, x2 - y2)
endfunction

private function UnitFilter takes unit u, player owner returns boolean
        return IsUnitEnemy(u, owner) /*
        */ and UnitAlive(u) /*
        */ and not IsUnitType(u, UNIT_TYPE_STRUCTURE)
endfunction

private function DistanceXY2D takes real X, real Y, real X2, real Y2 returns real
    return SquareRoot((X2 - X) * (X2 - X) + (Y2 - Y) * (Y2 - Y))
endfunction

private function Parabola takes real h, real d, real x returns real
    return (4 * h / d) * (d - x) * (x / d)
endfunction

private function StunTarget takes unit c,unit t,real sec returns nothing
   local unit d = CreateUnit(GetOwningPlayer(c),'h000',-70.,-2240,0.)
   local integer i = R2I(sec / .05)
   call UnitApplyTimedLife(d,'BLTF',1.)
   call UnitAddAbility(d,'stun')
   call SetUnitAbilityLevel(d,'stun',i)
   call IssueTargetOrder(d,"thunderbolt",t)
   set c = null
   set d = null
endfunction

   private struct data
      unit c
      unit dummy
      real x
      real y
      real angle
      real speed
      real height
      real cur
      real distance
      integer count
      player owner
      effect e
      timer tick
 
      method Onmove takes nothing returns nothing
         call SetUnitX(.dummy,.x)
         call SetUnitY(.dummy,.y)
         call SetUnitFlyHeight(.dummy,Parabola(.height,.cur,.distance),0.)
      endmethod
 
      method onDestroy takes nothing returns nothing
      local unit u
      local real angle
         set bj_lastCreatedTerrainDeformation = TerrainDeformCrater(.x,.y, 275., 80., R2I(0.15 * 1000), false)
         call DestroyEffect(AddSpecialEffect("war3mapImported\\NewDirtEXNofire.mdx",.x,.y))
         call DestroyEffect(.e)
         call RemoveUnit(.dummy)
     
         call GroupUnitsInArea(ENUM_GROUP,.x,.y,250)
           loop
           set u = FirstOfGroup(ENUM_GROUP)
           exitwhen u == null
           call GroupRemoveUnit(ENUM_GROUP,u)
            if UnitFilter(u,.owner) then
               set angle =  AngleBetweenPointsXY( GetUnitY(u),GetUnitY(.dummy),GetUnitX(u),GetUnitX(.dummy) )
               call UnitDamageTarget(.c,u,50.,false,false,ATTACK_TYPE_CHAOS,null,null)
               call StunTarget(.c,u,1.25+0.25*GetUnitAbilityLevel(.c,AbilityID))
               call KBs(u,35.,angle,null,1.50)
            endif
         endloop
     
         set  .c = null
         set  .e = null
         set  .dummy = null
         set  .owner = null
         call ClearTimerStructA(.tick)
         call ReleaseTimer(.tick)
      endmethod
   endstruct
 
private function Act takes nothing returns nothing
local data d = GetTimerStructA(GetExpiredTimer())
set d.distance = d.distance - d.speed
set d.x = d.x + d.speed*Cos(d.angle*bj_DEGTORAD)
set d.y = d.y + d.speed*Sin(d.angle*bj_DEGTORAD)
if d.distance <=0. then
   if d.count <= 0. then
      call d.onDestroy()
   else
      set d.distance = GetRandomReal(10.,20.)+d.cur/2.50
      set d.cur = d.distance
      set d.height = d.distance/4.
      set d.speed = d.distance/25
   endif
   set d.count = d.count - 1
else
   if d.cur > 500. and d.height > 250. then
      call d.Onmove()
   else
      if IsTerrainPathable(d.x-35., d.y-35., PATHING_TYPE_WALKABILITY) then
         set d.angle = d.angle - GetRandomReal(90,180)
      else
         call d.Onmove()
      endif
   endif
endif
endfunction

private function Action takes nothing returns nothing
local data d = data.create()
local real ty
local real tx
set d.c = GetTriggerUnit()
set d.x = GetUnitX(d.c)
set d.y = GetUnitY(d.c)
set tx  = GetSpellTargetX()
set ty  = GetSpellTargetY()
set d.owner = GetOwningPlayer(d.c)

if DistanceXY2D(d.x,d.y,tx,ty) <= 300. then
   set d.count    = GetRandomInt(1,2)
else
   set d.count    = GetRandomInt(2,3)
endif

set d.angle    = AngleBetweenPointsXY(ty,d.y,tx,d.x)
set d.height   = DistanceXY2D(d.x,d.y,tx,ty)/2.50
set d.speed    = DistanceXY2D(d.x,d.y,tx,ty)/35.
set d.cur      = DistanceXY2D(d.x,d.y,tx,ty)
set d.distance = DistanceXY2D(d.x,d.y,tx,ty)
set d.dummy  = CreateUnit(d.owner,DummyID,d.x,d.y,d.angle)
set d.e = AddSpecialEffectTarget("Abilities\\Spells\\NightElf\\CorrosiveBreath\\CorrosiveBreathMissile.mdl",d.dummy,"chest")
set d.x = GetUnitX(d.dummy)
set d.y = GetUnitY(d.dummy)

set d.tick = NewTimer()
call SetTimerStructA(d.tick,d)
call TimerStart(d.tick,0.031250000,true,function Act)
endfunction
//===========================================================================
private function Init takes nothing returns nothing
    local unit d = CreateUnit(Player(15),'h000',0.,0.,0.)
    call UnitAddAbility(d,'stun')
    call UnitRemoveAbility(d,'stun')
    call RemoveUnit(d)
    //===========================================================================
    call RegisterSpellEffectEvent(AbilityID,function Action)
    set  d = null
endfunction
endscope
Contents

Grenadle (Map)

Reviews
Tank-Commander
I looked through the code so I have a few quick notes: - something that stuck out in particular was the lack of a configuration, there's a lot of constants in there - you also need to give your spell a proper description, pasting the code with no...
I looked through the code so I have a few quick notes:
- something that stuck out in particular was the lack of a configuration, there's a lot of constants in there
- you also need to give your spell a proper description, pasting the code with no explanation for what the spell is or what it's intended to do just makes the reviewing process slower, though that also needs to be fixed as mentioned above with the indentation fixed also
- I'd also strongly recommend against utilizing terrain deformations
- your spell doesn't filter out air targets but can damage them (this would cause a visual error when the spell is cast at air units)

the lack of any configuration at all is issue enough to put this onto needs fix, I hope you'll update the description and fix the above mentioned issues so we can get this approved for you
 
Top