• 🏆 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!

Need help with this script

Status
Not open for further replies.
Level 13
Joined
Aug 19, 2014
Messages
1,111
Hello guys I need someone to take a look at this script

JASS:
scope CrazyIvan initializer init
    globals
        private constant integer SPELL_ID = 'A000'        //The raw code of the triggering ability
        private constant string TICK_SOUND_FX = "Sound\\Interface\\BattleNetTick.wav"        //the sound effect that plays when the timer ticks, use "" if you want no sound.
        private constant string EXPLODING_EFFECT = "ExplosionBIG.mdx"         //The effect that is created when the unit explodes
        private constant string BURNING_EFFECT = "Environment\\LargeBuildingFire\\LargeBuildingFire2.mdl"         //The burning effect on the bombed target.
        private constant string SEC_EXPLODING_EFFECT = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"         //The effect that is created when the unit explodes   
        private constant boolean EXPLODE_UNIT = FALSE       //Whether to make the unit explode, doing so will leave no corpse 
        private constant boolean BOMB_KILL_TARGET = false       //Whether to kill the bombed target or just deal damage to it.
        private constant boolean DO_AIRBORN = FALSE       //Whether to throw all damaged units in the air after the explosion
        private constant boolean SHOW_TIME = true        //Whether to show the time left before the unit explodes above it to all the players
        private constant boolean GET_CREDITS = true        //Whether to get credits when the unit explodes giving you experience and bounty
        private constant boolean BOMB_CONTINUE = true        //Whether to still explode the unit even if it dies
        private constant boolean BOMB_PAUSE = false          //Whether to pause the target unit on the effect
        private constant boolean BOMB_INVULNERABLE = false        //Whether to make the target invulnerable on the effect.
        private constant real TICK_INTERVAL = .0335        //The interval of the ticking timer. Doesn't do much but only checks numbers and set the vertex colors and textag
        private constant real TEXT_SIZE = .0239        //The size of the floating text above the target unit. Adjust it sensitively
        private constant real AIRBORN_BASE_TIME = 0.0       //Units further away last less on air, the real time isn't the base time, it's just a base value.
        private constant real AIRBORN_BASE_DIST = 0.0        //The airborn distance, units further away go in a decreased distance
        private constant real BASE_DAMAGE = 150        //The base damage of the aoe
        private constant real INCREMENT_DAMAGE = 150        //The increment damage per level
        private constant real BASE_TIME = 5       //The base amount of time in seconds after the unit explodes 
        private constant real DECREMENT_TIME = 0.0        //The decrement time in second per level of the spell (Level 1 = 12, Level 2 = 9, Level 3 = 6) and so on...
        private constant real BASE_RADIUS = 300        //The base area of effect of the explosion
        private constant real INCREMENT_RADIUS = 0.0        //The increment area of effect per level for the explosion
        private constant attacktype ATK_TYPE = ATTACK_TYPE_CHAOS        //The attack type of the damage dealt to nearby enemy untis
        private constant damagetype DMG_TYPE = DAMAGE_TYPE_DEMOLITION        //The damage type of the damage dealt to nearby enemy units
        private constant weapontype WEP_TYPE = WEAPON_TYPE_WHOKNOWS        //The weapon type of the damage dealt to nearby enemy units

    endglobals
    
    globals
        private constant boolean                     AFFECT_MAGIC_IMMUNE = false
        private constant boolean                     AFFECT_INVISIBLE    = true
        private constant boolean                     AFFECT_STRUCTURES   = false
        private constant boolean                     AFFECT_HEROES       = true
        private constant boolean                     AFFECT_ALLIES       = false
        private constant boolean                     AFFECT_ANCIENTS       = false
        private constant boolean                     AFFECT_FLYING       = false
        //This is the filter for the damage and airborn of the units that are close to the bombed target.
        //I think that affecting flying units on airborn wouldn't be quite a good idea.
    endglobals    
//===========================KHANT TOUCH DIS=========================================////
    globals
        private unit TempUnit
        private unit TempTarget
        private real TempDamage
        private constant group TempGroup = CreateGroup  (  )
    endglobals    
    
private function JumpParabola takes real d, real md, real c returns real
    local real t = (d*2) / md-1
    return (-t*t+1) * (md/c)
endfunction    

private function Shift takes real r returns real
    if (r < 120) then
        return 1.25
    elseif (r < 300) and (r > 119) then
        return 1.5
    elseif (r < 450) and (r > 299) then
        return 1.75
    elseif r > 449 then
        return 2.0
    endif
    return 1.4
endfunction    
    
private struct Airborn
    unit u
    real left
    real g
    real d
    real c    
    real sin
    real cos
    real i = 0    
    real p
    /////*
    static real MIN_X
    static real MIN_Y
    static real MAX_X
    static real MAX_Y
    static location loc = Location(0, 0)
    static location locx = Location(0, 0)
    static timer tim = CreateTimer()
    static thistype array arr
    static integer Total = 0
    /////*
    static method create takes unit u, integer time, real x, real y, real c returns thistype
        local thistype that = thistype.allocate()   
        local real tx = GetUnitX(u)
        local real ty = GetUnitY(u)
        local real dx = tx - x
        local real dy = ty - y
        local real a = Atan2(y - ty, x - tx)
        local location loc1 = Location(tx, ty)
        local location loc2 = Location(x, y)
        set that.sin = Sin(a)
        set that.cos = Cos(a)              
        set that.u = u
        set that.left = time
        set that.g = SquareRoot(dx * dx + dy * dy)
        set that.d = that.g / time
        set that.c = c
        call MoveLocation(thistype.loc, tx, ty)  
        set that.p = (GetLocationZ(loc2) - GetLocationZ(loc1)) / time
        call RemoveLocation(loc1)
        call RemoveLocation(loc2)   
        set loc1 = null
        set loc2 = null
        call UnitAddAbility(u, 'Amrf')
        call UnitRemoveAbility(u, 'Amrf')
        call PauseUnit(u, true)
        if thistype.Total == 0 then
            call TimerStart(thistype.tim, .0305, true, function thistype.Execute)
        endif
        set thistype.Total = thistype.Total + 1
        set thistype.arr[thistype.Total -1] = that
        return that
    endmethod

    static method Execute takes nothing returns nothing
    local thistype that
    local integer i = 0
    local real x
    local real y
    local real h
    local rect r
    local location l
    loop
        exitwhen i >= thistype.Total
        set that = thistype.arr[i]
        set x = GetUnitX(that.u) + (that.d) * that.cos
        set y = GetUnitY(that.u) + (that.d) * that.sin
        call MoveLocation(thistype.locx, x, y) 
        set h = JumpParabola(that.d * that.i, that.g, that.c) - (GetLocationZ(thistype.locx) - GetLocationZ(thistype.loc)) + that.p * that.i
        if x < thistype.MAX_X and y < thistype.MAX_Y and x > thistype.MIN_X and y > thistype.MIN_Y then
            call SetUnitX(that.u, x)
            call SetUnitY(that.u, y)
        endif        
        call SetUnitFlyHeight(that.u, h, 0)        
        if (that.i >= that.left) or (GetWidgetLife(that.u)<.405) then
            call that.destroy()
            set thistype.Total = thistype.Total - 1
            set thistype.arr[i] = thistype.arr[thistype.Total]
        else
            set that.i = that.i + 1
        endif
        
        set i = i + 1
    endloop
    
    if thistype.Total == 0 then
        call PauseTimer(thistype.tim)
    endif
    
    set l = null
    endmethod

    method onDestroy takes nothing returns nothing
        call SetUnitFlyHeight(.u, 0, 0)
        call PauseUnit(.u, false)
        call DestroyEffect(AddSpecialEffectTarget("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl", .u, "origin"))
        set .u = null
    endmethod
    
    static method Init takes nothing returns nothing
        set thistype.MAX_X = GetRectMaxX(bj_mapInitialPlayableArea) - 64
        set thistype.MAX_Y = GetRectMaxY(bj_mapInitialPlayableArea) - 64
        set thistype.MIN_X = GetRectMinX(bj_mapInitialPlayableArea) + 64
        set thistype.MIN_Y = GetRectMinY(bj_mapInitialPlayableArea) + 64
    endmethod
endstruct   

private function filter takes nothing returns boolean
    local unit u=GetFilterUnit()
    local boolean array b
    local real k
    local real x
    local real y
    local real tx
    local real ty
    local real ang
    local real dist
    local real c = 1.2
    if (GetWidgetLife(u)>.405) then
        set b[0] = IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) == false
        set b[1] = IsUnitType(u, UNIT_TYPE_STRUCTURE) == false
        set b[2] = IsUnitType(u, UNIT_TYPE_HERO) == false
        set b[3] = IsUnitType(u, UNIT_TYPE_ANCIENT) == false
        set b[4] = IsUnitType(u, UNIT_TYPE_FLYING) == false
        set b[5] = IsUnitVisible(u, GetOwningPlayer(TempUnit)) == true
        set b[6] = IsUnitAlly(u, GetOwningPlayer(TempUnit)) == false
        static if AFFECT_MAGIC_IMMUNE then
            set b[0] = true
        endif
        static if AFFECT_STRUCTURES then
            set b[1] = true
        endif
        static if AFFECT_HEROES then
            set b[2] = true
        endif
        static if AFFECT_ANCIENTS then
            set b[3] = true
        endif
        static if AFFECT_FLYING then
            set b[4] = true
        endif
        static if AFFECT_INVISIBLES then
            set b[5] = true
        endif
        static if AFFECT_ALLIES then
            set b[6] = true
        endif
        if (b[1] and b[2] and b[3] and b[4] and b[5] and b[6]) then
           call UnitDamageTarget(TempUnit,u , TempDamage, false, false, ATK_TYPE, DMG_TYPE, WEP_TYPE) 
           call DestroyEffect(AddSpecialEffectTarget( SEC_EXPLODING_EFFECT, u, "chest"))
           static if (DO_AIRBORN) then   
               set tx = GetUnitX(u)
               set ty = GetUnitY(u)   
               set x = GetUnitX(TempTarget) - tx
               set y = GetUnitY(TempTarget) - ty
               set k = SquareRoot(x * x + y * y)
               set dist = AIRBORN_BASE_DIST - (k * .6575)
               set x = GetUnitX(TempTarget)
               set y = GetUnitY(TempTarget)
               set ang = bj_RADTODEG * Atan2(ty - y, tx - x)
               set x = tx + dist * Cos(ang * bj_DEGTORAD)
               set y = ty + dist * Sin(ang * bj_DEGTORAD)
               set k = AIRBORN_BASE_TIME - c
               if k < .20 then
                   set k = .2
               endif    
               set k = k / .0305
               call Airborn.create(u, R2I(k), x, y, c)
           endif    
        endif
     endif
     set u=null
     return false
endfunction 
    
private struct boom
    unit u
    unit t
    real red = 255
    real time
    real rate
    real radius
    real dmg
    real tick = 0
    sound snd
    texttag txt
    effect art
    //
    real x
    real y
    //
    static integer max = 0
    static thistype array arr
    static timer tim = CreateTimer ( )
    //
    static method create takes unit u, unit t returns thistype
        local thistype this = thistype.allocate    (  )
        local integer l = GetUnitAbilityLevel(u, SPELL_ID)
        set this.u = u
        set this.t = t
        set this.time = (BASE_TIME + DECREMENT_TIME) - (DECREMENT_TIME * I2R(l))
        set this.rate = (this.red / this.time) * TICK_INTERVAL
        set this.radius = (BASE_RADIUS-INCREMENT_RADIUS) + (INCREMENT_RADIUS *I2R(l))
        set this.dmg = (BASE_DAMAGE - INCREMENT_DAMAGE) + (INCREMENT_DAMAGE * I2R(l))
        static if BOMB_PAUSE then
            call PauseUnit(this.u, true)
        endif
        static if BOMB_INVULNERABLE then
            call SetUnitInvulnerable(this.u, true)
        endif    
        set this.txt = CreateTextTag()
        set this.art = AddSpecialEffectTarget(BURNING_EFFECT, this.t, "overhead")
        call SetTextTagText(this.txt, I2S(R2I(this.time)), TEXT_SIZE)
        call SetTextTagPermanent(this.txt, false)
        call SetTextTagLifespan(this.txt, this.time-.15)
        static if SHOW_TIME then
            call SetTextTagVisibility(this.txt, true)
        else
            call SetTextTagVisibility(this.txt, false)
            if GetLocalPlayer() == GetOwningPlayer(this.u) then
                call SetTextTagVisibility(this.txt, true)
            endif
        endif
        if thistype.max == 0 then
            call TimerStart(thistype.tim, TICK_INTERVAL, true, function thistype.Exec)
        endif
        set thistype.max = thistype.max + 1
        set thistype.arr[thistype.max - 1] = this
        return this
    endmethod
    
        
    method explode takes nothing returns nothing
        set TempUnit=.u
        set TempDamage=.dmg
        set TempTarget = .t
        call GroupEnumUnitsInRange(TempGroup, .x, .y, this.radius,Condition(function filter))
        call DestroyEffect(AddSpecialEffectTarget(EXPLODING_EFFECT, .t, "chest"))
        static if EXPLODE_UNIT then
            call SetUnitExploded(.t, true)
        endif    
        static if GET_CREDITS then
            static if BOMB_INVULNERABLE then
                call SetUnitInvulnerable(.t, false)
            endif
            call UnitDamageTarget(.u, .t, 9999999, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_DIVINE, WEAPON_TYPE_WHOKNOWS)
        else
            static if BOMB_KILL_TARGET then
                call KillUnit(.t)
            endif    
        endif
        call DestroyEffect(.art)
        call .destroy()
    endmethod
    
    static method Exec takes nothing returns nothing
        local thistype this
        local integer i = 0
        loop
        exitwhen i>= thistype.max
            set this = thistype.arr[i]
            set this.time = this.time - TICK_INTERVAL
            set this.tick = this.tick + TICK_INTERVAL
            if this.tick > .9 then
                if TICK_SOUND_FX != "" then
                    set this.snd = CreateSound(TICK_SOUND_FX, false, true, true, 12710, 12710, "")
                    call AttachSoundToUnit(this.snd, this.t)
                    call StartSound(this.snd)
                    call KillSoundWhenDone(this.snd)
                    set this.snd = null
                    set this.tick = 0
                endif    
            endif    
            if GetWidgetLife(this.t)<.405 then
                call SetUnitVertexColor(this.t, 255, 255, 255, 255)
                static if BOMB_CONTINUE then
                    call this.explode()
                else
                    set thistype.max = thistype.max - 1
                    set thistype.arr[i] = thistype.arr[thistype.max]
                    call this.destroy()
                endif    
            else
                set this.x = GetUnitX(this.t)
                set this.y = GetUnitY(this.t)
                call SetTextTagPosUnit(this.txt, this.t, 0)
                if this.time < 1 then
                    call SetTextTagText(this.txt, "!!", TEXT_SIZE+.0085)
                else    
                    call SetTextTagText(this.txt, I2S(R2I(this.time)), TEXT_SIZE)
                endif    
                set this.red = this.red - this.rate
                call SetUnitVertexColor(this.t, 255, R2I(this.red), R2I(this.red), 255)
                call SetTextTagColor(this.txt, 255, R2I(this.red), R2I(this.red), 255)
            endif    
            if this.time < TICK_INTERVAL then
                call this.explode()
                set thistype.max = thistype.max - 1
                set thistype.arr[i] = thistype.arr[thistype.max]
            endif    
            set i = i + 1
        endloop
        if thistype.max == 0 then
            call PauseTimer(thistype.tim)
        endif
    endmethod
    
    method onDestroy takes nothing returns nothing
        call DestroyTextTag(.txt)
        set .txt = null
        set .u = null
        set .art = null
        set .t = null
    endmethod
    
endstruct
///=======================IRRELEVANT===================================================////

private function Bomb takes nothing returns boolean
    if GetSpellAbilityId() == SPELL_ID then
        call boom.create(GetTriggerUnit(), GetSpellTargetUnit())
    endif
    return false
endfunction   
    
private function init takes nothing returns nothing
    local trigger t = CreateTrigger      (  )
    call TriggerAddCondition(t, Condition(function Bomb))
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    set t = null
    call Airborn.Init()
endfunction

endscope

The spell kills the target regardless of its health even if I set this to False

JASS:
private constant boolean BOMB_KILL_TARGET = false       //Whether to kill the bombed target or just deal damage to it.

This is the link from the spell section http://www.hiveworkshop.com/forums/...75971/?prev=search=organic%20bomb&d=list&r=20
 
Last edited:
Level 14
Joined
Jul 1, 2008
Messages
1,314
Might it be, that the unit are constantly seen as INVULNERABLE and that GET_CREDITS is constantly on? This would mean, that it would not be affectedd by ur BOMB_KILL_TARGET variable ...


Here:
JASS:
static if EXPLODE_UNIT then
            call SetUnitExploded(.t, true)
        endif    
        static if GET_CREDITS then
            static if BOMB_INVULNERABLE then
                call SetUnitInvulnerable(.t, false)
            endif
            call UnitDamageTarget(.u, .t, 9999999, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_DIVINE, WEAPON_TYPE_WHOKNOWS)
        else
            static if BOMB_KILL_TARGET then
                call KillUnit(.t)
            endif    
        endif

just a side note, because i am interreseted, why do u do

JASS:
static if BOMB_INVULNERABLE then
                call SetUnitInvulnerable(.t, false)
            endif
            call UnitDamageTarget(.u, .t, 9999999, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_DIVINE, WEAPON_TYPE_WHOKNOWS)

instead of

JASS:
static if not BOMB_INVULNERABLE then
            call UnitDamageTarget(.u, .t, 9999999, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_DIVINE, WEAPON_TYPE_WHOKNOWS)

?
 
Level 13
Joined
Aug 19, 2014
Messages
1,111
just a side note, because i am interreseted, why do u do

JASS:
static if BOMB_INVULNERABLE then
                call SetUnitInvulnerable(.t, false)
            endif
            call UnitDamageTarget(.u, .t, 9999999, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_DIVINE, WEAPON_TYPE_WHOKNOWS)

instead of

JASS:
static if not BOMB_INVULNERABLE then
            call UnitDamageTarget(.u, .t, 9999999, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_DIVINE, WEAPON_TYPE_WHOKNOWS)

?

I didn't do it, I just downloaded this to the spell section. Anyway I did what you said and it works, also I removed the setting units color. Thanks man.

JASS:
scope CrazyIvan initializer init
    globals
        private constant integer SPELL_ID = 'A000'        //The raw code of the triggering ability
        private constant string TICK_SOUND_FX = "Sound\\Interface\\BattleNetTick.wav"        //the sound effect that plays when the timer ticks, use "" if you want no sound.
        private constant string EXPLODING_EFFECT = "ExplosionBIG.mdx"         //The effect that is created when the unit explodes
        private constant string BURNING_EFFECT = "Environment\\LargeBuildingFire\\LargeBuildingFire2.mdl"         //The burning effect on the bombed target.
        private constant string SEC_EXPLODING_EFFECT = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"         //The effect that is created when the unit explodes   
        private constant boolean EXPLODE_UNIT = FALSE       //Whether to make the unit explode, doing so will leave no corpse 
        private constant boolean BOMB_KILL_TARGET = false       //Whether to kill the bombed target or just deal damage to it.
        private constant boolean DO_AIRBORN = FALSE       //Whether to throw all damaged units in the air after the explosion
        private constant boolean SHOW_TIME = true        //Whether to show the time left before the unit explodes above it to all the players
        private constant boolean GET_CREDITS = true        //Whether to get credits when the unit explodes giving you experience and bounty
        private constant boolean BOMB_CONTINUE = true        //Whether to still explode the unit even if it dies
        private constant boolean BOMB_PAUSE = false          //Whether to pause the target unit on the effect
        private constant boolean BOMB_INVULNERABLE = false        //Whether to make the target invulnerable on the effect.
        private constant real TICK_INTERVAL = .0335        //The interval of the ticking timer. Doesn't do much but only checks numbers and set the vertex colors and textag
        private constant real TEXT_SIZE = .0239        //The size of the floating text above the target unit. Adjust it sensitively
        private constant real AIRBORN_BASE_TIME = 0.0       //Units further away last less on air, the real time isn't the base time, it's just a base value.
        private constant real AIRBORN_BASE_DIST = 0.0        //The airborn distance, units further away go in a decreased distance
        private constant real BASE_DAMAGE = 150        //The base damage of the aoe
        private constant real INCREMENT_DAMAGE = 150        //The increment damage per level
        private constant real BASE_TIME = 5       //The base amount of time in seconds after the unit explodes 
        private constant real DECREMENT_TIME = 0.0        //The decrement time in second per level of the spell (Level 1 = 12, Level 2 = 9, Level 3 = 6) and so on...
        private constant real BASE_RADIUS = 300        //The base area of effect of the explosion
        private constant real INCREMENT_RADIUS = 0.0        //The increment area of effect per level for the explosion
        private constant attacktype ATK_TYPE = ATTACK_TYPE_MAGIC        //The attack type of the damage dealt to nearby enemy untis
        private constant damagetype DMG_TYPE = DAMAGE_TYPE_NORMAL        //The damage type of the damage dealt to nearby enemy units
        private constant weapontype WEP_TYPE = WEAPON_TYPE_WHOKNOWS        //The weapon type of the damage dealt to nearby enemy units

    endglobals
    
    globals
        private constant boolean                     AFFECT_MAGIC_IMMUNE = false
        private constant boolean                     AFFECT_INVISIBLE    = true
        private constant boolean                     AFFECT_STRUCTURES   = false
        private constant boolean                     AFFECT_HEROES       = true
        private constant boolean                     AFFECT_ALLIES       = false
        private constant boolean                     AFFECT_ANCIENTS     = false
        private constant boolean                     AFFECT_FLYING       = false
        //This is the filter for the damage and airborn of the units that are close to the bombed target.
        //I think that affecting flying units on airborn wouldn't be quite a good idea.
    endglobals    
//===========================KHANT TOUCH DIS=========================================////
    globals
        private unit TempUnit
        private unit TempTarget
        private real TempDamage
        private constant group TempGroup = CreateGroup  (  )
    endglobals    
    
private function JumpParabola takes real d, real md, real c returns real
    local real t = (d*2) / md-1
    return (-t*t+1) * (md/c)
endfunction    

private function Shift takes real r returns real
    if (r < 120) then
        return 1.25
    elseif (r < 300) and (r > 119) then
        return 1.5
    elseif (r < 450) and (r > 299) then
        return 1.75
    elseif r > 449 then
        return 2.0
    endif
    return 1.4
endfunction    
    
private struct Airborn
    unit u
    real left
    real g
    real d
    real c    
    real sin
    real cos
    real i = 0    
    real p
    /////*
    static real MIN_X
    static real MIN_Y
    static real MAX_X
    static real MAX_Y
    static location loc = Location(0, 0)
    static location locx = Location(0, 0)
    static timer tim = CreateTimer()
    static thistype array arr
    static integer Total = 0
    /////*
    static method create takes unit u, integer time, real x, real y, real c returns thistype
        local thistype that = thistype.allocate()   
        local real tx = GetUnitX(u)
        local real ty = GetUnitY(u)
        local real dx = tx - x
        local real dy = ty - y
        local real a = Atan2(y - ty, x - tx)
        local location loc1 = Location(tx, ty)
        local location loc2 = Location(x, y)
        set that.sin = Sin(a)
        set that.cos = Cos(a)              
        set that.u = u
        set that.left = time
        set that.g = SquareRoot(dx * dx + dy * dy)
        set that.d = that.g / time
        set that.c = c
        call MoveLocation(thistype.loc, tx, ty)  
        set that.p = (GetLocationZ(loc2) - GetLocationZ(loc1)) / time
        call RemoveLocation(loc1)
        call RemoveLocation(loc2)   
        set loc1 = null
        set loc2 = null
        call UnitAddAbility(u, 'Amrf')
        call UnitRemoveAbility(u, 'Amrf')
        call PauseUnit(u, true)
        if thistype.Total == 0 then
            call TimerStart(thistype.tim, .0305, true, function thistype.Execute)
        endif
        set thistype.Total = thistype.Total + 1
        set thistype.arr[thistype.Total -1] = that
        return that
    endmethod

    static method Execute takes nothing returns nothing
    local thistype that
    local integer i = 0
    local real x
    local real y
    local real h
    local rect r
    local location l
    loop
        exitwhen i >= thistype.Total
        set that = thistype.arr[i]
        set x = GetUnitX(that.u) + (that.d) * that.cos
        set y = GetUnitY(that.u) + (that.d) * that.sin
        call MoveLocation(thistype.locx, x, y) 
        set h = JumpParabola(that.d * that.i, that.g, that.c) - (GetLocationZ(thistype.locx) - GetLocationZ(thistype.loc)) + that.p * that.i
        if x < thistype.MAX_X and y < thistype.MAX_Y and x > thistype.MIN_X and y > thistype.MIN_Y then
            call SetUnitX(that.u, x)
            call SetUnitY(that.u, y)
        endif        
        call SetUnitFlyHeight(that.u, h, 0)        
        if (that.i >= that.left) or (GetWidgetLife(that.u)<.405) then
            call that.destroy()
            set thistype.Total = thistype.Total - 1
            set thistype.arr[i] = thistype.arr[thistype.Total]
        else
            set that.i = that.i + 1
        endif
        
        set i = i + 1
    endloop
    
    if thistype.Total == 0 then
        call PauseTimer(thistype.tim)
    endif
    
    set l = null
    endmethod

    method onDestroy takes nothing returns nothing
        call SetUnitFlyHeight(.u, 0, 0)
        call PauseUnit(.u, false)
        call DestroyEffect(AddSpecialEffectTarget("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl", .u, "origin"))
        set .u = null
    endmethod
    
    static method Init takes nothing returns nothing
        set thistype.MAX_X = GetRectMaxX(bj_mapInitialPlayableArea) - 64
        set thistype.MAX_Y = GetRectMaxY(bj_mapInitialPlayableArea) - 64
        set thistype.MIN_X = GetRectMinX(bj_mapInitialPlayableArea) + 64
        set thistype.MIN_Y = GetRectMinY(bj_mapInitialPlayableArea) + 64
    endmethod
endstruct   

private function filter takes nothing returns boolean
    local unit u=GetFilterUnit()
    local boolean array b
    local real k
    local real x
    local real y
    local real tx
    local real ty
    local real ang
    local real dist
    local real c = 1.2
    if (GetWidgetLife(u)>.405) then
        set b[0] = IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) == false
        set b[1] = IsUnitType(u, UNIT_TYPE_STRUCTURE) == false
        set b[2] = IsUnitType(u, UNIT_TYPE_HERO) == false
        set b[3] = IsUnitType(u, UNIT_TYPE_ANCIENT) == false
        set b[4] = IsUnitType(u, UNIT_TYPE_FLYING) == false
        set b[5] = IsUnitVisible(u, GetOwningPlayer(TempUnit)) == true
        set b[6] = IsUnitAlly(u, GetOwningPlayer(TempUnit)) == false
        static if AFFECT_MAGIC_IMMUNE then
            set b[0] = true
        endif
        static if AFFECT_STRUCTURES then
            set b[1] = true
        endif
        static if AFFECT_HEROES then
            set b[2] = true
        endif
        static if AFFECT_ANCIENTS then
            set b[3] = true
        endif
        static if AFFECT_FLYING then
            set b[4] = true
        endif
        static if AFFECT_INVISIBLES then
            set b[5] = true
        endif
        static if AFFECT_ALLIES then
            set b[6] = true
        endif
        if (b[1] and b[2] and b[3] and b[4] and b[5] and b[6]) then
           call UnitDamageTarget(TempUnit,u , TempDamage, false, false, ATK_TYPE, DMG_TYPE, WEP_TYPE) 
           call DestroyEffect(AddSpecialEffectTarget( SEC_EXPLODING_EFFECT, u, "chest"))
           static if (DO_AIRBORN) then   
               set tx = GetUnitX(u)
               set ty = GetUnitY(u)   
               set x = GetUnitX(TempTarget) - tx
               set y = GetUnitY(TempTarget) - ty
               set k = SquareRoot(x * x + y * y)
               set dist = AIRBORN_BASE_DIST - (k * .6575)
               set x = GetUnitX(TempTarget)
               set y = GetUnitY(TempTarget)
               set ang = bj_RADTODEG * Atan2(ty - y, tx - x)
               set x = tx + dist * Cos(ang * bj_DEGTORAD)
               set y = ty + dist * Sin(ang * bj_DEGTORAD)
               set k = AIRBORN_BASE_TIME - c
               if k < .20 then
                   set k = .2
               endif    
               set k = k / .0305
               call Airborn.create(u, R2I(k), x, y, c)
           endif    
        endif
     endif
     set u=null
     return false
endfunction 
    
private struct boom
    unit u
    unit t
    real red = 255
    real time
    real rate
    real radius
    real dmg
    real tick = 0
    sound snd
    texttag txt
    effect art
    //
    real x
    real y
    //
    static integer max = 0
    static thistype array arr
    static timer tim = CreateTimer ( )
    //
    static method create takes unit u, unit t returns thistype
        local thistype this = thistype.allocate    (  )
        local integer l = GetUnitAbilityLevel(u, SPELL_ID)
        set this.u = u
        set this.t = t
        set this.time = (BASE_TIME + DECREMENT_TIME) - (DECREMENT_TIME * I2R(l))
        set this.rate = (this.red / this.time) * TICK_INTERVAL
        set this.radius = (BASE_RADIUS-INCREMENT_RADIUS) + (INCREMENT_RADIUS *I2R(l))
        set this.dmg = (BASE_DAMAGE - INCREMENT_DAMAGE) + (INCREMENT_DAMAGE * I2R(l))
        static if BOMB_PAUSE then
            call PauseUnit(this.u, true)
        endif
        static if BOMB_INVULNERABLE then
            call SetUnitInvulnerable(this.u, true)
        endif    
        set this.txt = CreateTextTag()
        set this.art = AddSpecialEffectTarget(BURNING_EFFECT, this.t, "overhead")
        call SetTextTagText(this.txt, I2S(R2I(this.time)), TEXT_SIZE)
        call SetTextTagPermanent(this.txt, false)
        call SetTextTagLifespan(this.txt, this.time-.15)
        static if SHOW_TIME then
            call SetTextTagVisibility(this.txt, true)
        else
            call SetTextTagVisibility(this.txt, false)
            if GetLocalPlayer() == GetOwningPlayer(this.u) then
                call SetTextTagVisibility(this.txt, true)
            endif
        endif
        if thistype.max == 0 then
            call TimerStart(thistype.tim, TICK_INTERVAL, true, function thistype.Exec)
        endif
        set thistype.max = thistype.max + 1
        set thistype.arr[thistype.max - 1] = this
        return this
    endmethod
    
        
    method explode takes nothing returns nothing
        set TempUnit=.u
        set TempDamage=.dmg
        set TempTarget = .t
        call GroupEnumUnitsInRange(TempGroup, .x, .y, this.radius,Condition(function filter))
        call DestroyEffect(AddSpecialEffectTarget(EXPLODING_EFFECT, .t, "chest"))
        static if EXPLODE_UNIT then
            call SetUnitExploded(.t, true)
        endif    
        static if GET_CREDITS then
            static if BOMB_INVULNERABLE then
                    call UnitDamageTarget(.u, .t, 9999999, false, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
        endif
            static if BOMB_KILL_TARGET then
                call KillUnit(.t)
            endif    
        endif
        call DestroyEffect(.art)
        call .destroy()
    endmethod
    
    static method Exec takes nothing returns nothing
        local thistype this
        local integer i = 0
        loop
        exitwhen i>= thistype.max
            set this = thistype.arr[i]
            set this.time = this.time - TICK_INTERVAL
            set this.tick = this.tick + TICK_INTERVAL
            if this.tick > .9 then
                if TICK_SOUND_FX != "" then
                    set this.snd = CreateSound(TICK_SOUND_FX, false, true, true, 12710, 12710, "")
                    call AttachSoundToUnit(this.snd, this.t)
                    call StartSound(this.snd)
                    call KillSoundWhenDone(this.snd)
                    set this.snd = null
                    set this.tick = 0
                endif    
            else
                set this.x = GetUnitX(this.t)
                set this.y = GetUnitY(this.t)
                call SetTextTagPosUnit(this.txt, this.t, 0)
                if this.time < 1 then
                    call SetTextTagText(this.txt, "!!", TEXT_SIZE+.0085)
                else    
                    call SetTextTagText(this.txt, I2S(R2I(this.time)), TEXT_SIZE)
                endif    
                set this.red = this.red - this.rate
                call SetTextTagColor(this.txt, 255, R2I(this.red), R2I(this.red), 255)
            endif    
            if this.time < TICK_INTERVAL then
                call this.explode()
                set thistype.max = thistype.max - 1
                set thistype.arr[i] = thistype.arr[thistype.max]
            endif    
            set i = i + 1
        endloop
        if thistype.max == 0 then
            call PauseTimer(thistype.tim)
        endif
    endmethod
    
    method onDestroy takes nothing returns nothing
        call DestroyTextTag(.txt)
        set .txt = null
        set .u = null
        set .art = null
        set .t = null
    endmethod
    
endstruct
///=======================IRRELEVANT===================================================////

private function Bomb takes nothing returns boolean
    if GetSpellAbilityId() == SPELL_ID then
        call boom.create(GetTriggerUnit(), GetSpellTargetUnit())
    endif
    return false
endfunction   
    
private function init takes nothing returns nothing
    local trigger t = CreateTrigger      (  )
    call TriggerAddCondition(t, Condition(function Bomb))
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    set t = null
    call Airborn.Init()
endfunction

endscope
 
Level 14
Joined
Jul 1, 2008
Messages
1,314
I didn't do it, I just downloaded this to the spell section. Anyway I did what you said and it works, also I removed the setting units color. Thanks man.

oh I see, well I am glad it works for u now. Just be aware that this spell was meant to kill the target unit whatever happens, as this is also written in its description:

JASS:
On cast:
Implants an organic bomb to a target enemy unit, making it explode after a set amount of time, damaging nearby enemy units and knocking them airborn.

So if u do not want to kill the target unit, I would suggest to keep the original system code and try to set (keep the BOMB_KILL_TARGET thing to FALSE):

JASS:
private constant boolean GET_CREDITS = FALSE

because of
JASS:
     [B]   static if GET_CREDITS then[/B]
            static if BOMB_INVULNERABLE then
                call SetUnitInvulnerable(.t, false)
            endif
            call UnitDamageTarget(.u, .t, 9999999, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_DIVINE, WEAPON_TYPE_WHOKNOWS)
        else
            static if BOMB_KILL_TARGET then
                call KillUnit(.t)
            endif    
        endif

u can also just put the whole explotion into comment brakets:

JASS:
     /*   static if EXPLODE_UNIT then
            call SetUnitExploded(.t, true)
        endif    
        static if GET_CREDITS then
            static if BOMB_INVULNERABLE then
                call SetUnitInvulnerable(.t, false)
            endif
            call UnitDamageTarget(.u, .t, 9999999, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_DIVINE, WEAPON_TYPE_WHOKNOWS)
        else
            static if BOMB_KILL_TARGET then
                call KillUnit(.t)
            endif    
        endif */

But as I said, I would not change the original code as this system can be adjusted anyway via the global constants.
 
Level 13
Joined
Aug 19, 2014
Messages
1,111
So if u do not want to kill the target unit, I would suggest to keep the original system code and try to set (keep the BOMB_KILL_TARGET thing to FALSE):

My only problem here is that the target unit is killed regardless of its health, lets say the damage of the spell is 150 and the target unit had 1000 health. It will instantly kill the target unit, even if I set that to False. But its working now and thanks for the help.
 
Status
Not open for further replies.
Top