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

JASS Code adjustment requests

Status
Not open for further replies.
Level 12
Joined
May 16, 2020
Messages
660
Hi guys,

Unfortunately I know zero JASS, which is why I'm opening a request for something which would be rather simple in GUI. I really need to learn the basics of JASS...

The requests are regarding the attached map and is for adjustments to 3 spells in there:

Black Hole
- Fix: There is an error in the code; the dummy unit's ability doesn't increase with the caster ability level
- I want to update the Black Hole visuals as in the attached image. For this I want to create another dummy unit (the AEO effect), at the same spot where the main Black Hole stands, with the same duration. Is it possible to add a line of code so that I can simply include the "dummy2_id"?

JASS:
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope BlackHole

globals
    // Config. Globals:
    private constant integer abil_id = 'A002' // Black Hole ability rawcode
    private constant integer dummy_id = 'u000' // Black Hole unit rawcode
    private constant real pull = 1.75 // Distance pulled/interval
    private constant boolean fight = false // Whether units can fight against the pull
    private constant string sfx = "Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl" // Effect created on pulled units
 
    // Needed Globals:
    public trigger Trigger = null // Output trigger will be BlackHole_Trigger, which can be used publically
    private group G = CreateGroup()
    private player P = null
    private real X
    private real Y
endglobals
// Config. Functions:
private function Range takes integer lvl returns real
    return 400. // Area for pull/lvl
endfunction
// Damage is found on the Black Hole (Dummy) ability

private struct data
    unit hole
    unit u
    player p
    integer lvl
    real x
    real y
endstruct

private function Conditions takes nothing returns boolean
    return GetUnitTypeId(GetSummonedUnit())==dummy_id
endfunction
private function Filt takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit())>.405 and not IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and IsUnitEnemy(GetFilterUnit(),P)
endfunction
private function Effects takes nothing returns nothing
    local real x
    local real y
    local real ang
 
    set bj_ghoul[25] = GetEnumUnit()
    set x = GetUnitX(bj_ghoul[25])
    set y = GetUnitY(bj_ghoul[25])
    set ang = Atan2(Y-y,X-x)
    if fight then
        call SetUnitX(bj_ghoul[25],x+pull*Cos(ang))
        call SetUnitY(bj_ghoul[25],y+pull*Sin(ang))
    else
        call SetUnitPosition(bj_ghoul[25],x+pull*Cos(ang),y+pull*Sin(ang))
    endif
    call DestroyEffect(AddSpecialEffectTarget(sfx,bj_ghoul[25],"origin"))
endfunction
private function Movement takes nothing returns boolean
    local data d = TT_GetData()
 
    if GetWidgetLife(d.hole)<.405 then
        call d.destroy()
        return true
    endif
 
    call GroupClear(G)
    set P = d.p
    set X = d.x
    set Y = d.y
    call GroupEnumUnitsInRange(G,d.x,d.y,Range(d.lvl),Condition(function Filt))
    call ForGroup(G,function Effects)
    return false
endfunction
private function Actions takes nothing returns nothing
    local data d = data.create()
 
    set d.hole = GetSummonedUnit()
    set d.x = GetUnitX(d.hole)
    set d.y = GetUnitY(d.hole)
    set d.u = GetSummoningUnit()
    set d.p = GetOwningPlayer(d.u)
    set d.lvl = GetUnitAbilityLevel(d.u,abil_id)
    call TT_Start(function Movement,d)
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
    set Trigger = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( Trigger, EVENT_PLAYER_UNIT_SUMMON )
    call TriggerAddCondition( Trigger, Condition( function Conditions ) )
    call TriggerAddAction( Trigger, function Actions )
endfunction

endscope

Toss
Is it possible to add the following modification:
- If an enemy is tossed, he takes 20% increased damage (so 20% in addition to the 75*lvl; allies take only 20%)
- If the hero has the ability X, the 20% damage bonus increases to 35% / 50% / 65% for enemies. Allies take still only 20%

JASS:
//TESH.scrollpos=109
//TESH.alwaysfold=0
scope Toss

globals
    // Config Globals:
    private constant integer abil_id = 'A001' // Toss ability rawcode
    private constant integer fly_id = 'Amrf' // Rawcode of ability to use for fly trick, if you have not touched Crow Form, this doesn't need changing
    private constant real impact_damage = .20 // Percent of toss damage dealt to tossed unit
    private constant real time = 1. // Flight time for tossed unit (seconds)
    private constant string fly_sfx = "Abilities\\Spells\\Undead\\Cripple\\CrippleTarget.mdl" // Effect created on target during toss
    private constant string end_sfx = "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl" // Effect created on target at end of toss
    private constant boolean kill_trees = true // Whether trees are destroyed upon target landing
    private constant attacktype attack_type = ATTACK_TYPE_NORMAL // Attack type used for damage
    private constant damagetype damage_type = DAMAGE_TYPE_DEMOLITION // Damage type used for damage
 
    // Needed Globals:
    private group G = CreateGroup()
    private unit U = null
    private rect R = null
    private location L = null
    public trigger Trigger = null // Output trigger will be Toss_Trigger, which can be used publically
endglobals
// Config. Functions:
private function Damage takes integer lvl returns real
    return 75.*lvl // Damage/lvl
endfunction
private function Area takes integer lvl returns real
    return 275. // Area within to grab units and damage units/lvl
endfunction

//========================================================================================
private struct data
    unit u
    unit targ
    player p
    real xt
    real yt
    real xl
    real yl
    real dist
    real ang
    real cos
    real sin
    real speed
    real hc
    integer lvl
    integer count = 1
    effect e
 
    static method FiltIsEnemy takes nothing returns boolean
        return IsUnitEnemy(GetFilterUnit(), bj_groupEnumOwningPlayer) and GetUnitState(GetFilterUnit(),UNIT_STATE_LIFE)>.405
    endmethod
    static method DamageGroup takes unit damager, real radius, real x, real y, real amount returns nothing
        local unit u
 
        set bj_groupEnumOwningPlayer = GetOwningPlayer(damager)
        call GroupClear(G)
        call GroupEnumUnitsInRange(G, x, y, radius, Condition(function data.FiltIsEnemy))
        loop
            set u = FirstOfGroup(G)
            exitwhen u == null
            call GroupRemoveUnit(G,u)
            call UnitDamageTarget(damager,u,amount,false,false,attack_type,damage_type,null)
        endloop
    endmethod
    static method KillTrees_Child takes nothing returns nothing
        call KillDestructable(GetEnumDestructable()) 
    endmethod
    static method KillTrees takes real x, real y, real radius returns nothing
        set R = Rect(x - radius,y - radius,x + radius,y + radius)
 
        call EnumDestructablesInRect(R,null,function data.KillTrees_Child)
        call RemoveRect(R)
    endmethod
    method onDestroy takes nothing returns nothing
        call SetUnitFlyHeight(.targ,GetUnitDefaultFlyHeight(.targ),0.)
        call PauseUnit(.targ,false)
        call SetUnitPathing(.targ,true)
        call DestroyEffect(.e)
        call UnitDamageTarget(.u,.targ,Damage(.lvl)*impact_damage,false,false,attack_type,damage_type,null)
        call DestroyEffect(AddSpecialEffectTarget(end_sfx,.targ,"origin"))
        call data.DamageGroup(.u,Area(.lvl),.xl,.yl,Damage(.lvl))
        if kill_trees then
            call data.KillTrees(.xl,.yl,Area(.lvl))
        endif
    endmethod
endstruct

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == abil_id
endfunction
private function Filt takes nothing returns boolean
    return GetFilterUnit()!=U and GetWidgetLife(GetFilterUnit())>.405 and not IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and not IsUnitType(GetFilterUnit(),UNIT_TYPE_FLYING)
endfunction
private function GetSpeed takes real dist returns real
    return dist/(1./TT_PERIOD)
endfunction
private function GetCountConversion takes integer count returns real
    return (50./(time/TT_PERIOD))*count
endfunction
private function Movement takes nothing returns boolean
    local data d = TT_GetData()
    local real conv
    local real height
    local real speed
    local real x
    local real y
 
    if d.count<=time/TT_PERIOD then
        set conv = GetCountConversion(d.count)
        set height = (conv-25.)*(conv-25.)
        set speed = d.count*d.speed
        set x = d.xt+speed*d.cos
        set y = d.yt+speed*d.sin
        call SetUnitX(d.targ,x)
        call SetUnitY(d.targ,y)
        call SetUnitFlyHeight(d.targ,625.-height,0.)
        set d.count = d.count + 1
        return false
    else
        call d.destroy()
        return true
    endif
endfunction
private function Actions takes nothing returns nothing
    local data d = data.create()
 
    set d.u = GetTriggerUnit()
    set d.p = GetOwningPlayer(d.u)
    set d.lvl = GetUnitAbilityLevel(d.u,abil_id)
 
    call GroupClear(G)
    set U = d.u
    call GroupEnumUnitsInRange(G,GetUnitX(d.u),GetUnitY(d.u),Area(d.lvl),Condition(function Filt))
    set d.targ = GroupPickRandomUnit(G)
    if d.targ==null then
        call d.destroy()
        return
    endif
 
    set d.xt = GetUnitX(d.targ)
    set d.yt = GetUnitY(d.targ)
    set L = GetSpellTargetLoc()
    set d.xl = GetLocationX(L)
    set d.yl = GetLocationY(L)
    set d.ang = Atan2(d.yl-d.yt,d.xl-d.xt)
    set d.cos = Cos(d.ang)
    set d.sin = Sin(d.ang)
    set d.dist = SquareRoot((d.xt-d.xl)*(d.xt-d.xl) + (d.yt-d.yl)*(d.yt-d.yl))
    set d.speed = GetSpeed(d.dist)
 
    call PauseUnit(d.targ,true)
    call SetUnitPathing(d.targ,false)
    call UnitAddAbility(d.targ,fly_id)
    call UnitRemoveAbility(d.targ,fly_id)
    set d.e = AddSpecialEffectTarget(fly_sfx,d.targ,"origin")
 
    call TT_Start(function Movement,d)
 
    call RemoveLocation(L)
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
    set Trigger = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( Trigger, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( Trigger, Condition( function Conditions ) )
    call TriggerAddAction( Trigger, function Actions )
endfunction

endscope

Wild Axes
- For some reasons the axes don't always look into the correct direction. Is it possible to fix this?

JASS:
//TESH.scrollpos=67
//TESH.alwaysfold=0
scope WildAxes

globals
    // Config. Globals:
    private constant integer abil_id = 'A003' // Wild Axes ability rawcode
    private constant integer dummy_id = 'e000' // Wild Axes unit rawcode
    private constant real speed = .028 // Speed for axes, this is an arbitrary value, increasing it increases the axes speed, while decreasing it decreases their speed
    private constant real width = 375. // Width for bezier curve, larger values give a wider arc, and vice versa
    private constant real area = 150. // Area to damage units around axes and destroy trees
    private constant string sfx = "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl" // Effect created on hit units
    private constant attacktype attack_type = ATTACK_TYPE_NORMAL // Attack type for damage
    private constant damagetype damage_type = DAMAGE_TYPE_NORMAL // Damage type for damage
 
    // Needed Globals:
    public trigger Trigger = null // Output trigger will be WildAxes_Trigger, which can be used publically
    private group G = CreateGroup()
    private group TempG = null
    private player P = null
    private location L = null
    private rect R = null
endglobals
// Config. Functions:
private function Damage takes integer lvl returns real
    return 50.+(lvl*30.) // Damage/lvl
endfunction

private struct data
    unit u
    unit axe
    player p
    group grp
    real x
    real y
    real xl
    real yl
    real a = 1.
    real outx
    real outy
    real ang
    integer lvl
    boolean first = true
endstruct

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId()==abil_id
endfunction
private function Filt takes nothing returns boolean
    return not IsUnitInGroup(GetFilterUnit(),TempG) and GetWidgetLife(GetFilterUnit())>.405 and not IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and IsUnitEnemy(GetFilterUnit(),P)
endfunction
private function Kill_Trees takes nothing returns nothing
    call KillDestructable(GetEnumDestructable())
endfunction
private function Effects takes unit u, real x, real y, group grp, integer lvl returns nothing
    local unit dum
 
    set R = Rect(x-150.,y-150.,x+150.,y+150.)
    call EnumDestructablesInRect(R,null,function Kill_Trees)
    call RemoveRect(R)
    call GroupClear(G)
    set P = GetOwningPlayer(u)
    set TempG = grp
    call GroupEnumUnitsInRange(G,x,y,area,Condition(function Filt))
    loop
        set dum = FirstOfGroup(G)
        exitwhen dum==null
        call GroupRemoveUnit(G,dum)
        call UnitDamageTarget(u,dum,Damage(lvl),false,false,attack_type,damage_type,null)
        call DestroyEffect(AddSpecialEffectTarget(sfx,dum,"chest"))
        call GroupAddUnit(grp,dum)
    endloop
endfunction
private function Movement takes nothing returns boolean
    local data d = TT_GetData()
    local real b = 1.-d.a
 
    call SetUnitX(d.axe,d.x*d.a*d.a+d.outx*2*d.a*b+d.xl*b*b)
    call SetUnitY(d.axe,d.y*d.a*d.a+d.outy*2*d.a*b+d.yl*b*b)
    call Effects(d.u,GetUnitX(d.axe),GetUnitY(d.axe),d.grp,d.lvl)
    if d.first then
        set d.a = d.a-speed
    else
        set d.a = d.a+speed
        set d.x = GetUnitX(d.u)
        set d.y = GetUnitY(d.u)
    endif
    if d.a<0. and d.first then
        set d.first = false
        set d.outx = d.x+width*Cos(Atan2(d.yl-d.y,d.xl-d.x)+d.ang)
        set d.outy = d.y+width*Sin(Atan2(d.yl-d.y,d.xl-d.x)+d.ang)
    endif
    if d.a>1. and d.first==false then
        call DestroyGroup(d.grp)
        call RemoveUnit(d.axe)
        call d.destroy()
        return true
    endif
    return false
endfunction
private function Actions takes nothing returns nothing
    local data d1 = data.create()
    local data d2 = data.create()
 
    set d1.u = GetTriggerUnit()
    set d2.u = d1.u
    set d1.x = GetUnitX(d1.u)
    set d2.x = d1.x
    set d1.y = GetUnitY(d1.u)
    set d2.y = d1.y
    set d1.p = GetOwningPlayer(d1.u)
    set d2.p = d1.p
    set d1.axe = CreateUnit(d1.p,dummy_id,d1.x,d1.y,0.)
    set d2.axe = CreateUnit(d1.p,dummy_id,d1.x,d1.y,0.)
    set d1.grp = CreateGroup()
    set d2.grp = CreateGroup()
    set d1.lvl = GetUnitAbilityLevel(d1.u,abil_id)
    set d2.lvl = d1.lvl
    set L = GetSpellTargetLoc()
    set d1.xl = GetLocationX(L)
    set d2.xl = d1.xl
    set d1.yl = GetLocationY(L)
    set d2.yl = d1.yl
 
    set d1.outx = d1.x+width*Cos(Atan2(d1.yl-d1.y,d1.xl-d1.x)+45.)
    set d1.outy = d1.y+width*Sin(Atan2(d1.yl-d1.y,d1.xl-d1.x)+45.)
    set d2.outx = d1.x+width*Cos(Atan2(d1.yl-d1.y,d1.xl-d1.x)-45.)
    set d2.outy = d1.y+width*Sin(Atan2(d1.yl-d1.y,d1.xl-d1.x)-45.)
    set d1.ang = -45.
    set d2.ang = 45.
 
    call TT_Start(function Movement,d1)
    call TT_Start(function Movement,d2)
 
    call RemoveLocation(L)
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
    set Trigger = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( Trigger, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( Trigger, Condition( function Conditions ) )
    call TriggerAddAction( Trigger, function Actions )
endfunction

endscope


Thanks!
 

Attachments

  • emjlr3 - DotA Spell Pack 1 - Black Hole, Toss, Wild Axes Adjusted JASS.w3x
    80.9 KB · Views: 29
  • Blackhole.PNG
    Blackhole.PNG
    774.5 KB · Views: 33
Level 17
Joined
Mar 21, 2011
Messages
1,597
JASS:
private function Range takes integer lvl returns real
    return 400. // Area for pull/lvl
endfunction

this function will always return 400, regardless of the parameter. You have to adjust the function to something like this

JASS:
private function Range takes integer lvl returns real
    return 400. + lvl * 20 // Area for pull/lvl
endfunction


I dont quite understand how you want the toss ability to function?
Just a % damage increase on the target while tossed in the air?
 
Level 12
Joined
May 16, 2020
Messages
660
JASS:
private function Range takes integer lvl returns real
    return 400. // Area for pull/lvl
endfunction

this function will always return 400, regardless of the parameter. You have to adjust the function to something like this

JASS:
private function Range takes integer lvl returns real
    return 400. + lvl * 20 // Area for pull/lvl
endfunction


I dont quite understand how you want the toss ability to function?
Just a % damage increase on the target while tossed in the air?

Thanks for the answer! Mmm the 400 is fix, but that’s not really an issue. Let me describe better what Toss does (or should do)

- Toss distinguishes between tossing an "enemy" or an "ally"
- If an enemy is tossed, the enemy receives 1.2*75*toss_lvl damage
- If an ally is tossed, the ally receives only 0.2*75*toss_lvl damage
- If the hero has his ultimate leveled, the toss damage increases to (1.2+0.15*ultimate_lvl)*75*toss_lvl for enemies (and allies take (0.2+0.15*ultimate_lvl)*75*toss_lvl damage)

(if that doesn't help, maybe this spell page describes it better Tiny - Stone Giant, Skills, Item Builds | DotA Builds)

Does this help?
 
Level 17
Joined
Mar 21, 2011
Messages
1,597
- Toss distinguishes between tossing an "enemy" or an "ally"
- If an enemy is tossed, the enemy receives 1.2*75*toss_lvl damage
- If an ally is tossed, the ally receives only 0.2*75*toss_lvl damage
It does that already.

For the ulti part you need to add a new function
JASS:
private function ImpactDamage takes integer lvl returns real
    return 0.2 + 0.15 * lvl
endfunction

now you need to adjust one codeline in the onDestroy method:

JASS:
// Old line
call UnitDamageTarget(.u,.targ,Damage(.lvl)*impact_damage,false,false,attack_type,damage_type,null)

// New line
call UnitDamageTarget(.u,.targ,Damage(.lvl)*ImpactDamage(GetUnitAbilityLevel(this.u, 'ABIL')),false,false,attack_type,damage_type,null)

'Abil' needs to be replaced by your Grow! ability code
 
Level 12
Joined
May 16, 2020
Messages
660
It does that already.

For the ulti part you need to add a new function
JASS:
private function ImpactDamage takes integer lvl returns real
    return 0.2 + 0.15 * lvl
endfunction

now you need to adjust one codeline in the onDestroy method:

JASS:
// Old line
call UnitDamageTarget(.u,.targ,Damage(.lvl)*impact_damage,false,false,attack_type,damage_type,null)

// New line
call UnitDamageTarget(.u,.targ,Damage(.lvl)*ImpactDamage(GetUnitAbilityLevel(this.u, 'ABIL')),false,false,attack_type,damage_type,null)

'Abil' needs to be replaced by your Grow! ability code

Thank you - worked wonderfully! Can you please also review the other 2 questions when you have time?
 
Level 17
Joined
Mar 21, 2011
Messages
1,597
JASS:
call SetUnitAbilityLevel(d.hole, 'DUMMY_ABIL_CODE', d.lvl)

add this line between those 2 lines inside the Actions function and adjust the ability code for the dummy ability

JASS:
    set d.lvl = GetUnitAbilityLevel(d.u,abil_id)
    // -- Put it here
    call TT_Start(function Movement,d)

i will take a look at the 3rd ability when i have more time
 
Level 12
Joined
May 16, 2020
Messages
660
JASS:
call SetUnitAbilityLevel(d.hole, 'DUMMY_ABIL_CODE', d.lvl)

add this line between those 2 lines inside the Actions function and adjust the ability code for the dummy ability

JASS:
    set d.lvl = GetUnitAbilityLevel(d.u,abil_id)
    // -- Put it here
    call TT_Start(function Movement,d)

i will take a look at the 3rd ability when i have more time

Thanks, but I want to also "create a dummy unit at the target point of ability being cast", with a expiration time of 4 seconds. How would I do that?
 
Level 12
Joined
May 16, 2020
Messages
660
Yeah you are right, it's based on Tornado. The default ability already spawns the Black Hole "Unit" (=the black ball). But I want to also add another dummy unit which represents the dark circle.

Since it's based on a spawning unit, I figure an appropriate trigger would be:

1. IF Unit X is spawned (=the Black Hole)
2. THEN create unit Y (=my circle effect dummy unit) at "position of spawning unit"
3. Add generic expiration time to unit Y

... But don't know how to do that in JASS.
 

Attachments

  • Blackhole.PNG
    Blackhole.PNG
    774.5 KB · Views: 54
Level 12
Joined
May 16, 2020
Messages
660
I know right! I thought I remember from WC3 that it should be possible to use "auras" or for example "sphere" for a dummy unit with an effect as model and get a result - but in Reforged the effect doesn't show up when the dummy unit is an effect or missile etc....

So as workaround, I thought I would simply create a unit at the same spot and have the same effect
 
Level 17
Joined
Mar 21, 2011
Messages
1,597
Try this.
You need to adjust one global variable for the unit id of the effect dummy and the ability code for the dummy ability


JASS:
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope BlackHole

globals
    // Config. Globals:
    private constant integer abil_id = 'A002' // Black Hole ability rawcode
    private constant integer dummy_id = 'u000' // Black Hole unit rawcode
    private constant integer anim_id = 'YOUR_UNIT'
    private constant real pull = 1.75 // Distance pulled/interval
    private constant boolean fight = false // Whether units can fight against the pull
    private constant string sfx = "Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl" // Effect created on pulled units

    // Needed Globals:
    public trigger Trigger = null // Output trigger will be BlackHole_Trigger, which can be used publically
    private group G = CreateGroup()
    private player P = null
    private real X
    private real Y
endglobals
// Config. Functions:
private function Range takes integer lvl returns real
    return 400. // Area for pull/lvl
endfunction
// Damage is found on the Black Hole (Dummy) ability

private struct data
    unit hole
    unit u
    unit anim
    player p
    integer lvl
    real x
    real y
endstruct

private function Conditions takes nothing returns boolean
    return GetUnitTypeId(GetSummonedUnit())==dummy_id
endfunction
private function Filt takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit())>.405 and not IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and IsUnitEnemy(GetFilterUnit(),P)
endfunction
private function Effects takes nothing returns nothing
    local real x
    local real y
    local real ang

    set bj_ghoul[25] = GetEnumUnit()
    set x = GetUnitX(bj_ghoul[25])
    set y = GetUnitY(bj_ghoul[25])
    set ang = Atan2(Y-y,X-x)
    if fight then
        call SetUnitX(bj_ghoul[25],x+pull*Cos(ang))
        call SetUnitY(bj_ghoul[25],y+pull*Sin(ang))
    else
        call SetUnitPosition(bj_ghoul[25],x+pull*Cos(ang),y+pull*Sin(ang))
    endif
    call DestroyEffect(AddSpecialEffectTarget(sfx,bj_ghoul[25],"origin"))
endfunction
private function Movement takes nothing returns boolean
    local data d = TT_GetData()

    if GetWidgetLife(d.hole)<.405 then
        call RemoveUnit(d.anim)
        call d.destroy()
        return true
    endif

    call GroupClear(G)
    set P = d.p
    set X = d.x
    set Y = d.y
    call GroupEnumUnitsInRange(G,d.x,d.y,Range(d.lvl),Condition(function Filt))
    call ForGroup(G,function Effects)
    return false
endfunction
private function Actions takes nothing returns nothing
    local data d = data.create()

    set d.hole = GetSummonedUnit()
    set d.x = GetUnitX(d.hole)
    set d.y = GetUnitY(d.hole)
    set d.u = GetSummoningUnit()
    set d.p = GetOwningPlayer(d.u)
    set d.lvl = GetUnitAbilityLevel(d.u,abil_id)
    set d.anim = CreateUnit(d.p,anim_id,d.x,d.y,0.)
    call SetUnitAbilityLevel(d.hole, 'DUMMY_ABIL_CODE', d.lvl)
    call TT_Start(function Movement,d)
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
    set Trigger = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( Trigger, EVENT_PLAYER_UNIT_SUMMON )
    call TriggerAddCondition( Trigger, Condition( function Conditions ) )
    call TriggerAddAction( Trigger, function Actions )
endfunction

endscope
 
Status
Not open for further replies.
Top