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: 225

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: 189

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.
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top