New spell, and more trouble

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
JASS:
call GroupEnumUnitsInRange(g, dd.x, dd.y, Range, Filter (function Filters))


Range is a function, so you need to put Range()

BoundSentinel
I do not use it before in my map. =p

255 * (TRANSPARENCY / 100)
Put this, it compiles.
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
BoundSentinel doesn't need any requires/uses/needs... it do the stuff alone in background, basically it catch when the unit leave a delimited region by Vexorian, and replace it to the delimited limits, in order to avoid war3 crash.

Personally i don't use it because sometimes i need to put units outside the playable map area, and in the current version it doesn't allow this, and should be never, in order to avoid war3 crashs. (seems it crash only under special cases, and i've never got a crash by putting an unit outside the playable map area like i do, ofc i'm not trying silly stuff like giving it an order).

Also war3 crash if you try to put an unit outside the entire map.
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Oh, but I use a kind of preload system in my map, that creates units outside the camera bounds, so this won't work anymore ??? :S

Isn't there some other system which checks for the camera bounds, but only when you want to ??? :D

Ok, now the damage works :D But how about the other questions in my last post :S

And now another question came up... Why doesn't the caster recieve back the ability "Attack" when the spell is over ??? :(
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
Oh, but I use a kind of preload system in my map, that creates units outside the camera bounds, so this won't work anymore ??? :S

Depends what you want say by "this won't work anymore", the units will be created but will be moved to the playable map area.

Hmm ... no wait there is a way.
If you create units without any wait in a library initializer, just make BoundSentinel requires your library, the init of your library will be do before BoundSentinel's one, and then the leave events won't fire.
Maybe that was you wanted to say btw.

Isn't there some other system which checks for the camera bounds, but only when you want to ??? :D
The point of BoundSentinel is safety, be automatic, the user has nothing to do, and don't lost the performance with SetUnitX/Y with extra checkings.
But you can try to ask to Vexorian to add a function to temporally enable/disable this feature, it's very easy to do, but i don't believe he will do it, because the safety point is broken, but who know ?
At least if you don't know how to edit it, i can edit it for you but DON'T release anything with it or don't claim it's yours, it's Vexorian's

Ok, now the damage works :D But how about the other questions in my last post :S
Sorry but i don't wan't help more today, maybe later if it is still doesn't solved

And now another question came up... Why doesn't the caster recieve back the ability "Attack" when the spell is over ??? :(
You can remove 'Aatk' but can't add it, that's all, but you can morph the unit in this unit type.
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Bump :D

Maybe someone else can answer the questions he didn't ??? :eek:

EDIT: Here's an update, again:
JASS:
scope SearingDash initializer init

globals
    private constant integer ABIL_ID = 'A000' // The rawcode of the ability!
    private constant integer ATTACK_ID = 'Aatk' // The rawcode of the "Attack" ability!
    
    private constant string EFFECT_1 = "Environment\\SmallBuildingFire\\SmallBuildingFire2.mdl"
    private constant string ATTACH_POINT = "origin"
    
    private constant real DURATION = 5 //How long the spell lasts
    private constant real PERIOD = .03125 //Time between effects being created.
    private constant real DAMAGE_PERIOD = 0.5 // How often the effects deal damage.
    private constant real EFFECT_DURATION = 1.5 // How long the effects last.
    // This constant should be EFFECT_DURATION * 32.
    
    private constant attacktype ATTACK_TYPE = ATTACK_TYPE_NORMAL  // Explains itself i think XD
    private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL  // Same here <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite7" alt=":p" title="Stick Out Tongue    :p" loading="lazy" data-shortname=":p" />
    private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS// And same here <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin    :D" loading="lazy" data-shortname=":D" />
    
    private constant real DMG_FACTOR = 1. // An easy way of changing the damage!
    private constant real RNG_FACTOR = 1. // An easy way of changing the damage range!
    
    private constant integer TRANSPARENCY = 85 // In %, how transparent the caster becomes!
endglobals

globals
    private group g = CreateGroup()
    private integer TempStruct
endglobals

private struct Data
    real speed
    real time = 1
    unit caster
    player owner
    integer lvl
    boolean on
    real x1
    real x2
    real y1
    real y2
    real angle
    rect r
    
    static method create takes unit u returns Data
        local Data d = Data.allocate()
        set d.caster = u
        set d.owner = GetOwningPlayer(d.caster)
        set d.speed = GetUnitMoveSpeed(u)
        set d.lvl = GetUnitAbilityLevel(d.caster, ABIL_ID)
        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        call SetUnitMoveSpeed(.caster, .speed)
        call SetUnitPathing(.caster,true)
        call SetUnitVertexColor(.caster,255,255,255,255)
        call UnitAddAbility(.caster, ATTACK_ID)
        call SetPlayerAbilityAvailable(.owner, ABIL_ID, true)
        set .on = false
    endmethod
endstruct

private struct Dam
    unit caster
    player owner
    real x
    real y
    integer lv
    integer tick
endstruct

private function Damage takes nothing returns real
    return I2R( Dam(TempStruct).lv) * DMG_FACTOR * 10.
endfunction

private function Range takes nothing returns real
    return I2R( Dam(TempStruct).lv) * RNG_FACTOR * 50. + 50.
endfunction

private function Filters takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit()) &gt; 0.405 and IsUnitEnemy(GetFilterUnit(), Dam(TempStruct).owner) and IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false
endfunction

private function Spell_Check takes nothing returns boolean
    return GetSpellAbilityId() == ABIL_ID
endfunction

private function Is_On takes nothing returns boolean
    return Data(TempStruct).on
endfunction

private function Deal_Damage takes nothing returns nothing
    call UnitDamageTarget(Dam(TempStruct).caster, GetEnumUnit(), Damage(), true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
endfunction

private function Damage_Period takes nothing returns boolean
    local Dam dd = KT_GetData()
    if dd.tick &gt; 0 then
        set TempStruct = dd
        call GroupEnumUnitsInRange(g, dd.x, dd.y, Range(), Filter (function Filters))
        call ForGroup(g,function Deal_Damage)
        set dd.tick = dd.tick - 1
        return false
    else
        call dd.destroy()
    endif
    return true
endfunction

private function Periodic takes nothing returns boolean
    local Data d = KT_GetData()
    local Dam dd
    if d.time &lt; DURATION - PERIOD then
        set d.time = d.time + PERIOD
        set dd = Dam.create()
        set dd.caster = d.caster
        set dd.owner = d.owner
        set dd.x = GetUnitX(d.caster)
        set dd.y = GetUnitY(d.caster)
        set dd.lv = d.lvl
        set dd.tick = R2I(EFFECT_DURATION / DAMAGE_PERIOD)
        call KT_Add(function Damage_Period, dd, DAMAGE_PERIOD)
        call TE_TimedEffect(AddSpecialEffect(EFFECT_1,dd.x,dd.y), EFFECT_DURATION)
        return false
    else
        call d.destroy()
        return true
    endif
endfunction

private function Move_Function takes nothing returns boolean
    local Data d = KT_GetData()
    local real newx = d.x2 + 5 * Cos(d.angle * bj_DEGTORAD)
    local real newy = d.y2 + 5 * Sin(d.angle * bj_DEGTORAD)
    call BJDebugMsg(&quot;And this one too!&quot;)
    if (GetRectMinX(d.r) &lt;= newx) and (newx &lt;= GetRectMaxX(d.r)) and (GetRectMinY(d.r) &lt;= newy) and (newy &lt;= GetRectMaxY(d.r)) then
        call BJDebugMsg(&quot;We&#039;re here!&quot;)
        return true
    else
        call SetUnitX(d.caster, newx)
        call SetUnitY(d.caster, newy)
        call BJDebugMsg(&quot;And we&#039;re moving!&quot;)
    endif
    return false
endfunction
    
private function Move_Action takes nothing returns nothing
    local Data d = Data.create(GetTriggerUnit())
    set d.x1 = GetOrderPointX()
    set d.y1 = GetOrderPointY()
    set d.x2 = GetUnitX(d.caster)
    set d.y2 = GetUnitY(d.caster)
    set d.angle = bj_RADTODEG * Atan2(d.y1 - d.y1, d.x1 - d.x2)
    set d.r = Rect(d.x1 - 2.5, d.y1 - 2.5, d.x2 + 2.5, d.y2 + 2.5)
    call BJDebugMsg(&quot;It starts!&quot;)
    call KT_Add( function Move_Function, d, 0.05)
endfunction

private function Spell takes nothing returns nothing
    local Data D = Data.create(GetTriggerUnit())
    set D.on = true
    call SetUnitPathing(D.caster,false)
    call SetUnitVertexColor(D.caster,255,255,255,255 * (TRANSPARENCY / 100))
    call UnitRemoveAbility( D.caster, ATTACK_ID)
    call SetPlayerAbilityAvailable(D.owner, ABIL_ID, false)
    call KT_Add(function Periodic, D, PERIOD)
endfunction

private function init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t,Condition (function Spell_Check))
    call TriggerAddAction(t, function Spell)
    
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
    call TriggerAddCondition(t, Condition(function Is_On))
    call TriggerAddAction(t, function Move_Action)
endfunction
endscope


Now, I would believe that at least one of those debug msg'es would appear, but nothing :( why ??!?!?!!
And of course, the unit isn't moved faster either :(

EDIT2: Just noticed that if I remove this line:
JASS:
call TriggerAddCondition(t, Condition(function Is_On))


The messages at least show, but the whole spell bugs and the caster can barely move :S Might it be that structs can't pass members between triggers ??? :S

Any suggestions ??? :eek:
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Just gonna bump this one more, and also attach the map so everyone can see for themselves what happens and such ;)

And the caster still becomes totally invisible when you cast the spell... But also becomes completely visible when it ends, so that's good :D

And also, there seems to be a bug when you cast the spell quickly after it ends...
 

Attachments

  • Second Spell, by Komaqtion!.w3x
    36.2 KB · Views: 221

roXplosive

New Member
Reaction score
15
I would've posted again on the issue with the array size bu :nuts: I couldn't find the thread any more . Why didn't you change the variable from casting delay (time) to CastsPerSecond (Hz or time at -1 power) . That would have been an easy way around it .
 

Frozenhelfir

set Gwypaas = Guhveepaws
Reaction score
56
I somehow managed to get the firelord stuck :O I'll take a look at the code in a bit, i have some things to do.
 

Attachments

  • komaqtion stuck me!.w3g
    9 KB · Views: 184

Komaqtion

You can change this now in User CP.
Reaction score
469
Yeah, that is the bug I'm talking about... and he also "hacks" a little too :(
 

Frozenhelfir

set Gwypaas = Guhveepaws
Reaction score
56
My guess is you have an infinite loop setting his position to his current position. Just starting to look through the code, and wtf are all these functions for? I can see having the filter one and the spellcheck, but all of the others just reduce efficiency.

JASS:
private function Damage takes nothing returns real
    return I2R( Dam(TempStruct).lv) * DMG_FACTOR * 10.
endfunction

private function Range takes nothing returns real
    return I2R( Dam(TempStruct).lv) * RNG_FACTOR * 50. + 50.
endfunction

private function Filters takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit()) &gt; 0.405 and IsUnitEnemy(GetFilterUnit(), Dam(TempStruct).owner) and IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false
endfunction

private function Spell_Check takes nothing returns boolean
    return GetSpellAbilityId() == ABIL_ID
endfunction

private function Is_On takes nothing returns boolean
    return Data(TempStruct).on
endfunction

private function Deal_Damage takes nothing returns nothing
    call UnitDamageTarget(Dam(TempStruct).caster, GetEnumUnit(), Damage(), true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
endfunction
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Well, Deal_Damage is the function a timers executes when it expires, and it deals damage...

And those "Damage" and "Range" function are just configurables ;)

And the "Is_On" is a check for the potentially working "Move_Actions".
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Well, just gonna bump this again :p

C'mon people, I really need help here :D

(Not that I don't appriciate the massive amount of help I've already gotten, but :D)
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Works now :
JASS:
scope SearingDash initializer init

globals
    private constant integer ABIL_ID = &#039;A000&#039; // The rawcode of the ability!
    private constant integer ATTACK_ID = &#039;Aatk&#039; // The rawcode of the &quot;Attack&quot; ability!
    
    private constant string EFFECT_1 = &quot;Environment\\SmallBuildingFire\\SmallBuildingFire2.mdl&quot;
    private constant string ATTACH_POINT = &quot;origin&quot;
    
    private constant real DURATION = 5 //How long the spell lasts
    private constant real PERIOD = .03125 //Time between effects being created.
    private constant real DAMAGE_PERIOD = 0.5 // How often the effects deal damage.
    private constant real EFFECT_DURATION = 1.5 // How long the effects last.
    // This constant should be EFFECT_DURATION * 32.
    
    private constant attacktype ATTACK_TYPE = ATTACK_TYPE_NORMAL  // Explains itself i think XD
    private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL  // Same here <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite7" alt=":p" title="Stick Out Tongue    :p" loading="lazy" data-shortname=":p" />
    private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS// And same here <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin    :D" loading="lazy" data-shortname=":D" />
    
    private constant real DMG_FACTOR = 1. // An easy way of changing the damage!
    private constant real RNG_FACTOR = 1. // An easy way of changing the damage range!
    
    private constant integer TRANSPARENCY = 85 // In %, how transparent the caster becomes!
    private filterfunc Filterz
endglobals

globals
    private group g = CreateGroup()
    private integer TempStruct
endglobals

private struct Data
    real speed
    real time = 1
    unit caster
    player owner
    integer lvl
    boolean on
    //Moving checksum
    real origX
    real origY
    real x
    real y
    real angle
    
    static method create takes unit u returns Data
        local Data d = Data.allocate()
        set d.caster = u
        set d.owner = GetOwningPlayer(d.caster)
        set d.speed = GetUnitMoveSpeed(u)
        set d.lvl = GetUnitAbilityLevel(d.caster, ABIL_ID)
        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        call SetUnitMoveSpeed(.caster, .speed)
        call SetUnitPathing(.caster,true)
        call SetUnitVertexColor(.caster,255,255,255,255)
        call UnitAddAbility(.caster, ATTACK_ID)
        call SetPlayerAbilityAvailable(.owner, ABIL_ID, true)
        set .on = false
    endmethod
endstruct

private struct Dam
    unit caster
    player owner
    real x
    real y
    integer lv
    integer tick
endstruct

private function Damage takes nothing returns real
    return I2R( Dam(TempStruct).lv) * DMG_FACTOR * 10.
endfunction

private function Range takes nothing returns real
    return I2R( Dam(TempStruct).lv) * RNG_FACTOR * 50. + 50.
endfunction

private function Filters takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit()) &gt; 0.405 and IsUnitEnemy(GetFilterUnit(), Dam(TempStruct).owner) and IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false
endfunction

private function Spell_Check takes nothing returns boolean
    return GetSpellAbilityId() == ABIL_ID
endfunction

private function Is_On takes nothing returns boolean
    return Data(TempStruct).on
endfunction

private function Deal_Damage takes nothing returns nothing
    call UnitDamageTarget(Dam(TempStruct).caster, GetEnumUnit(), Damage(), true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
endfunction

private function Damage_Period takes nothing returns boolean
    local Dam dd = KT_GetData()
    if dd.tick &gt; 0 then
        set TempStruct = dd
        call GroupEnumUnitsInRange(g, dd.x, dd.y, Range(),Filterz)
        call ForGroup(g,function Deal_Damage)
        set dd.tick = dd.tick - 1
        return false
    else
        call dd.destroy()
    endif
    return true
endfunction

private function Periodic takes nothing returns boolean
    local Data d = KT_GetData()
    local Dam dd
    if d.time &lt; DURATION - PERIOD then
        set d.time = d.time + PERIOD
        set dd = Dam.create()
        set dd.caster = d.caster
        set dd.owner = d.owner
        set dd.x = GetUnitX(d.caster)
        set dd.y = GetUnitY(d.caster)
        set dd.lv = d.lvl
        set dd.tick = R2I(EFFECT_DURATION / DAMAGE_PERIOD)
        call KT_Add(function Damage_Period, dd, DAMAGE_PERIOD)
        call TE_TimedEffect(AddSpecialEffect(EFFECT_1,dd.x,dd.y), EFFECT_DURATION)
        set d.angle = GetUnitFacing(d.caster)
        set d.x = d.origX - dd.x
        set d.y = d.origY - dd.y
        if (d.x * d.x + d.y * d.y) &gt; 20. then//If the caster is moved, slide it slightly...
            set d.x = dd.x + 5. * Cos(d.angle * .0175)
            set d.y = dd.y + 5. * Sin(d.angle * .0175)
            call SetUnitX(d.caster,d.x)
            call SetUnitY(d.caster,d.y)
            set d.origX = d.x
            set d.origY = d.y
        endif
        return false
    else
        call d.destroy()
        return true
    endif
endfunction

private function Spell takes nothing returns nothing
    local Data D = Data.create(GetTriggerUnit())
    set D.on = true
    call SetUnitPathing(D.caster,false)
    call SetUnitVertexColor(D.caster,255,255,255,255 * (TRANSPARENCY / 100))
    call UnitRemoveAbility( D.caster, ATTACK_ID)
    call SetPlayerAbilityAvailable(D.owner, ABIL_ID, false)
    call KT_Add(function Periodic, D, PERIOD)
endfunction

private function init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t,Condition (function Spell_Check))
    call TriggerAddAction(t, function Spell)
    set Filterz = Filter(function Filters)
endfunction
endscope
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Yay ! Thanks :D

Now, I've solved the problem with the insivibility thing by myself now, but still... How can I disable the attack option of the caster ??? I've tried adding Cargo Hold (Tank) to him, but nothing happens :(
 

roXplosive

New Member
Reaction score
15
WHen do you want to have his attack disabled ? Always ? If so go to the object editor and change his Combat - enabled attacks to none .

Else set his secondary attack to none and make him metamorph into himself .
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Well, since this is as spell which I will be submitting here (probably) I don't want to have many custom units and stuff for people to import, which is why I just want to disable attack while the spell is on.

But I found a solution, silly me, I just tried using the Cargo Hold (Orc Burrow) and works great now :D

Should I submit my problems (If I bump into more with this spell) in this thread, or create a new one ??? :S
 

roXplosive

New Member
Reaction score
15
How should I know ? BTW your problems seem helpful for others to take heed and learn . This is cool ... now I know how to disable my skills when I want so . I plan on making some autocast skills that disable normal attack .
 

Komaqtion

You can change this now in User CP.
Reaction score
469
I've now gotten quite far on this spell, though there is one thing troubling me...

I would really like the damage intervals to be united, so that there's a "global" damage over all the effects, every second...

Because now they deal damage every second, starting when they were created, which is different for each effect :(

Any ideas ??? :eek:

Here's the current code:

JASS:
scope SearingDash initializer init

globals
    private constant integer ABIL_ID = &#039;A000&#039; // The rawcode of the ability!
    private constant integer CARGO_ID = &#039;Abun&#039; // The rawcode of the &quot;Cargo Hold&quot; ability!
    
    private constant string EFFECT_1 = &quot;Environment\\SmallBuildingFire\\SmallBuildingFire2.mdl&quot;
    private constant string ATTACH_POINT = &quot;origin&quot;
    
    private constant string DMG_EFFECT = &quot;Abilities\\Spells\\Items\\AIfb\\AIfbSpecialArt.mdl&quot;
    private constant string ATTACH_POINT2 = &quot;chest&quot;
    
    private constant real DURATION = 5 //How long the spell lasts
    private constant real PERIOD = .03125 //Time between effects being created.
    private constant real DAMAGE_PERIOD = 0.5 // How often the effects deal damage.
    private constant real EFFECT_DURATION = 1.5 // How long the effects last.
    
    private constant attacktype ATTACK_TYPE = ATTACK_TYPE_NORMAL  // Explains itself i think XD
    private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL  // Same here <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite7" alt=":p" title="Stick Out Tongue    :p" loading="lazy" data-shortname=":p" />
    private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS// And same here <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite8" alt=":D" title="Big Grin    :D" loading="lazy" data-shortname=":D" />
    
    private constant real DMG_FACTOR = 1. // An easy way of changing the damage!
    private constant real RNG_FACTOR = 1. // An easy way of changing the damage range!
    
    private constant real TRANSPARENCY = 45. // In %, how transparent the caster becomes!
endglobals

globals
    private group g = CreateGroup()
    private integer TempStruct
    private filterfunc Filterz
endglobals

private struct Data
    real speed
    real time = 1
    unit caster
    player owner
    integer lvl
    //Moving checksum
    real origX
    real origY
    real x
    real y
    real angle
    real scale = 1.
    
    static method create takes unit u returns Data
        local Data d = Data.allocate()
        set d.caster = u
        set d.owner = GetOwningPlayer(d.caster)
        set d.speed = GetUnitMoveSpeed(u)
        set d.lvl = GetUnitAbilityLevel(d.caster, ABIL_ID)
        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        call SetUnitMoveSpeed(.caster, .speed)
        call SetUnitPathing(.caster,true)
        call SetUnitVertexColor(.caster,255,255,255,255)
        call SetPlayerAbilityAvailable(.owner, ABIL_ID, true)
        call UnitRemoveAbility(.caster, CARGO_ID)
    endmethod
endstruct

private struct Dam
    unit caster
    player owner
    real x
    real y
    integer lv
    integer tick
endstruct

private function Damage takes nothing returns real
    return I2R(Dam(TempStruct).lv) * DMG_FACTOR * 10.
endfunction

private function Range takes nothing returns real
    return I2R(Dam(TempStruct).lv) * RNG_FACTOR * 50. + 50.
endfunction

private function Filters takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit()) &gt; 0.405 and IsUnitEnemy(GetFilterUnit(), Dam(TempStruct).owner) and IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false
endfunction

private function Spell_Check takes nothing returns boolean
    return GetSpellAbilityId() == ABIL_ID
endfunction

private function Deal_Damage takes nothing returns nothing
    call UnitDamageTarget(Dam(TempStruct).caster, GetEnumUnit(), Damage(), true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
    call DestroyEffect(AddSpecialEffectTarget(DMG_EFFECT, GetEnumUnit(), ATTACH_POINT2))
endfunction

private function Damage_Period takes nothing returns boolean
    local Dam dd = KT_GetData()
    if dd.tick &gt; 0 then
        set TempStruct = dd
        call GroupEnumUnitsInRange(g, dd.x, dd.y, Range(),Filterz)
        call ForGroup(g,function Deal_Damage)
        set dd.tick = dd.tick - 1
        return false
    else
        call dd.destroy()
    endif
    return true
endfunction

private function Descaling takes nothing returns boolean
    local Data d = KT_GetData()
    if d.scale &gt; 1. then
        set d.scale = d.scale - 0.05
        call SetUnitScale(d.caster, d.scale, d.scale, d.scale)
        return false
    else
        return true
    endif
endfunction

private function Scaling takes nothing returns boolean
    local Data d = KT_GetData()
    if d.scale &lt; 1.65 then
        set d.scale = d.scale + 0.05
        call SetUnitScale(d.caster, d.scale, d.scale, d.scale)
        return false
    else
        return true
    endif
endfunction

private function Periodic takes nothing returns boolean
    local Data d = KT_GetData()
    local Dam dd
    if d.time &lt; DURATION - PERIOD then
        set d.time = d.time + PERIOD
        set dd = Dam.create()
        set dd.caster = d.caster
        set dd.owner = d.owner
        set dd.x = GetUnitX(d.caster)
        set dd.y = GetUnitY(d.caster)
        set dd.lv = d.lvl
        set dd.tick = R2I(EFFECT_DURATION / DAMAGE_PERIOD)
        call KT_Add(function Damage_Period, dd, DAMAGE_PERIOD)
        call TE_TimedEffect(AddSpecialEffect(EFFECT_1,dd.x,dd.y), EFFECT_DURATION)
        set d.angle = GetUnitFacing(d.caster)
        set d.x = d.origX - dd.x
        set d.y = d.origY - dd.y
        if (d.x * d.x + d.y * d.y) &gt; 20. then
            set d.x = dd.x + 5. * Cos(d.angle * .0175)
            set d.y = dd.y + 5. * Sin(d.angle * .0175)
            call SetUnitX(d.caster,d.x)
            call SetUnitY(d.caster,d.y)
            set d.origX = d.x
            set d.origY = d.y
        endif
        return false
    else
        call d.destroy()
        call KT_Add( function Descaling, d, PERIOD)
        return true
    endif
endfunction

private function Spell takes nothing returns nothing
    local Data D = Data.create(GetTriggerUnit())
    call SetUnitPathing(D.caster,false)
    call SetUnitVertexColor(D.caster,255,255,255,R2I(255. * TRANSPARENCY / 100.))
    call UnitAddAbility(D.caster, CARGO_ID)
    call SetPlayerAbilityAvailable(D.owner, ABIL_ID, false)
    call KT_Add(function Periodic, D, PERIOD)
    call KT_Add(function Scaling, D, PERIOD)
endfunction

private function init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t,Condition (function Spell_Check))
    call TriggerAddAction(t, function Spell)
    set Filterz = Filter(function Filters)
endfunction
endscope
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      • Ghan
        Administrator - Servers are fun

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top