New spell, and more trouble

Komaqtion

You can change this now in User CP.
Reaction score
469
But I want different periods, one for the duration of the effect, and one for how often one effect is created :D
 

Frozenhelfir

set Gwypaas = Guhveepaws
Reaction score
56
Could be done with a textmacro if you can trust the end user with it :eek:

edit: Ewww! TheHelper shows textmacros as comments in JASS tags...

JASS:
scope SearingDash initializer init

globals
    private constant integer ABIL_ID = 'A000'
    private constant string EFFECT_1 = "Environment\\SmallBuildingFire\\SmallBuildingFire2.mdl"
    private constant real DURATION = 5 //How long the spell lasts
    private constant real PERIOD = .1 //Time between 'ticks'
endglobals

//Polar bears are fluffy!

//effectDuration MUST be a whole number. 
//effectDuration decides how many periods the effect lasts 
//DO NOT CHANGE THIS TEXT MACRO! CHANGE THE ONE RIGHT AFTER private struct Data!!
//! textmacro effectInit takes effectDuration
    effect array e[$effectDuration$]
    integer eMax = $effectDuration$ - 1
//! endtextmacro

private struct Data
//CHANGE effectDuration HERE!
//Chance the number inside the quotes "X" DO NOT REMOVE ZE QUOTES!!!
//! runtextmacro effectInit("4") 
    integer i = 0
    real x
    real y
    real speed
    real time = 1
    unit caster
    timer t
    static method create takes unit u returns Data
        local Data d = Data.allocate()
        set d.caster = u
        set d.t = NewTimer()
        set d.x = GetUnitX(u)
        set d.y = GetUnitY(u)
        set d.speed = GetUnitMoveSpeed(u)
        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        local integer i=0
        loop //this is just in case :O
            call DestroyEffect(.e<i>)
            exitwhen i &gt;= .eMax
            set i=i+1
        endloop
        call SetUnitMoveSpeed(.caster, .speed)
        call SetUnitPathing(.caster,true)
        call SetUnitVertexColor(.caster,255,255,255,100)
    endmethod
endstruct

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

private function Periodic takes nothing returns boolean
    local Data d = KT_GetData()
    if d.time &lt; DURATION - PERIOD then
        set d.time = d.time + PERIOD
        set d.x = GetUnitX(d.caster)
        set d.y = GetUnitY(d.caster)
        if d.i &gt;= d.eMax then
            set d.i = 0
        endif
        call DestroyEffect(d.e[d.i]) //I&#039;m not sure if this will crash thread if there isn&#039;t an effect there
        //if it does just add one in the initializer <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" />
        set d.e[d.i] = AddSpecialEffect(EFFECT_1,d.x,d.y)
        set d.i = d.i+1
        return false
    else
        call SetUnitMoveSpeed(d.caster, d.speed)
        call SetUnitPathing(d.caster,true)
        call SetUnitVertexColor(d.caster,255,255,255,100)
        call d.destroy()
        return true
    endif
endfunction

private function Spell takes nothing returns nothing
    local Data D = Data.create(GetTriggerUnit())
    call SetUnitMoveSpeed(D.caster, 522)
    call SetUnitPathing(D.caster,false)
    call SetUnitVertexColor(D.caster,255,255,255,85)
    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)
endfunction
endscope</i>
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Sorry, but it isn't working :( I set the duration to 10, buyt they still go away after like 1 sec or so :(

EDIT: No, wait... Just kidding, I just saw now that it's the number of periods, and not seconds and i changed the periods to 0.03125 so...
Is there a way to use seconds instead ?
 

Frozenhelfir

set Gwypaas = Guhveepaws
Reaction score
56
Didn't see the edit when I replied to it nor when the screen came back up. Anyway, its better to leave it at periods because it is more customizable. Plus, if you want it to last in seconds, the user can go start -> accessories -> calculator and figure it out with 1/PERIOD. That could be added in a comment. I'm just stating that if I were to use that spell it would be much better to be able to determine that via periods.

EDIT: I don't think seconds would be possible because you can't put variables in the [] or do math in the [], so the burden does fall on the user. If you go the seconds route without putting the burden on the user, you'll have to use 8190 size just to be safe.
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Ok, well this is what I've done now...

I've created a small snippet (Timed Effect) which I use now, instead of that array:
JASS:
library TE requires KT

private struct SFX
    effect sfx

    method onDestroy takes nothing returns nothing
        call DestroyEffect(.sfx)
    endmethod
endstruct

private function Destroy takes nothing returns boolean
    call SFX(KT_GetData()).destroy()
    return true
endfunction

public function TimedEffect takes effect e, real duration returns nothing
    local SFX d = SFX.create()
    set d.sfx = e
    call KT_Add(function Destroy,d,duration)
endfunction

endlibrary


And I now create dummy units at the same place as the effects, to be able to deal damage later on (Haven't gotten that far yet), but here's an update :D
JASS:
scope SearingDash initializer init

globals
    private constant integer ABIL_ID = &#039;A000&#039;
    private constant integer DUMMY_ID = &#039;h000&#039;
    private constant integer BUFF_ID = &#039;BTLF&#039;
    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 = 1 // How often the effects deal damage.
    private constant real EFFECT_DURATION = 1.5 // How long the effects last.
    private constant integer EFFECT_PERIODS = 48 // Here you have to do some calculation yourself.
    // This constant should be EFFECT_DURATION * 32.
endglobals

globals
    private group g = CreateGroup()
endglobals

private struct Data
    unit array dummy[EFFECT_PERIODS]
    integer i = 0
    real x
    real y
    real speed
    real time = 1
    unit caster
    player owner
    timer t
    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.t = CreateTimer()
        set d.x = GetUnitX(u)
        set d.y = GetUnitY(u)
        set d.speed = GetUnitMoveSpeed(u)
        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        call SetUnitMoveSpeed(.caster, .speed)
        call SetUnitPathing(.caster,true)
        call SetUnitVertexColor(.caster,255,255,255,100)
    endmethod
endstruct

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

private function Damage_Period takes nothing returns boolean
    local Data d = KT_GetData()
    if d.time &lt; DURATION - PERIOD then
    return false
    else
    return true
    endif
endfunction

private function Periodic takes nothing returns boolean
    local Data d = KT_GetData()
    if d.time &lt; DURATION - PERIOD then
        set d.time = d.time + PERIOD
        set d.x = GetUnitX(d.caster)
        set d.y = GetUnitY(d.caster)
        set d.dummy[d.i] = CreateUnit(d.owner, DUMMY_ID,d.x,d.y, bj_UNIT_FACING)
        call UnitApplyTimedLife(d.dummy[d.i],BUFF_ID,EFFECT_DURATION)
        call KT_Add( function Damage_Period, d, DAMAGE_PERIOD)
        call TE_TimedEffect(AddSpecialEffect(EFFECT_1,GetUnitX( d.dummy[d.i]),GetUnitY( d.dummy[d.i])), EFFECT_DURATION)
        set d.i = d.i+1
        return false
    else
        call d.destroy()
        return true
    endif
endfunction

private function Spell takes nothing returns nothing
    local Data D = Data.create(GetTriggerUnit())
    call SetUnitMoveSpeed(D.caster, 522)
    call SetUnitPathing(D.caster,false)
    call SetUnitVertexColor(D.caster,255,255,255,85)
    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)
endfunction
endscope


Any optimization suggestions would be nice :D
 

Frozenhelfir

set Gwypaas = Guhveepaws
Reaction score
56
JASS:
unit array dummy[EFFECT_PERIODS]


That compiles? >.> Will look thru the rest of the code in a bit

edit: as far as omptimization goes, creating a unit AND an effect every frame is very 'un'-optimized. I think you should really look into a different way of doing this.
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Why wouldn't it compile ??? :S

What should I do about the units and effects then ??? :S
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Actually put an effect as an instance into the library is inefficient, the best way is clear it all in an instance. Why not add an EffectGroup in the library?
 

Frozenhelfir

set Gwypaas = Guhveepaws
Reaction score
56
>Why wouldn't it compile ??? :S

It wouldn't with the effect array. I just noticed that for constants the compiler probably just copies/pastes the value. So as long as you just put an integer in there it should be good to go. As for taking the unit creation out, why not just use x/y?
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
JASS:
Effect Grouping Tool v1

by kingking

Effect Group type : egroup

Functions provided :
function CreateEGroup takes nothing returns egroup
function EGroupAddEffect takes egroup g, effect e returns nothing
function EGroupPickRandomEffect takes egroup g returns effect
function FirstOfEGroup takes egroup g returns effect
function CountEffectsInEGroup takes egroup g returns integer
function EGroupRemoveEffect takes egroup g, effect e returns nothing
function ForEGroup takes egroup g, code c returns nothing
function GetEnumEffect takes nothing returns effect
function EGroupClear takes egroup g returns nothing
function DestroyEGroup takes egroup g returns nothing


JASS:
library EGroup

globals
    private constant integer MAX_EFFECTS_IN_GROUP = 100
    private effect EGroup_Effect = null
endglobals

//////////////////////////////////NO MORE TOUCHING//////////////////////////////////////////
struct egroup
    effect array e [MAX_EFFECTS_IN_GROUP]
    integer effectcount = 0
    trigger callback = CreateTrigger()
    
    method onDestroy takes nothing returns nothing
        set .effectcount = 0
    endmethod
endstruct

function CreateEGroup takes nothing returns egroup
    return egroup.create()
endfunction

function EGroupAddEffect takes egroup g, effect e returns nothing
    set egroup(g).effectcount = egroup(g).effectcount + 1
    set egroup(g).e[egroup(g).effectcount] = e
endfunction

function EGroupPickRandomEffect takes egroup g returns effect
    return egroup(g).e[GetRandomInt(1,egroup(g).effectcount)]
endfunction

function FirstOfEGroup takes egroup g returns effect
    return egroup(g).e[1]
endfunction

function CountEffectsInEGroup takes egroup g returns integer
    return egroup(g).effectcount
endfunction

function EGroupRemoveEffect takes egroup g, effect e returns nothing
    local integer i = 1
    local boolean b = false
    loop
    exitwhen i &gt; egroup(g).effectcount or b == true
        if egroup(g).e<i> == e then
            set egroup(g).e<i> = egroup(g).e[egroup(g).effectcount]
            set egroup(g).e[egroup(g).effectcount] = null
            set egroup(g).effectcount = egroup(g).effectcount - 1
            set b = true
        endif
        set i = i + 1
    endloop
endfunction

function GetEnumEffect takes nothing returns effect
    return EGroup_Effect
endfunction

function ForEGroup takes egroup g, code c returns nothing
    local integer i = 1
    local triggeraction ta = TriggerAddAction(egroup(g).callback,c)
    loop
    exitwhen i &gt; egroup(g).effectcount
        set EGroup_Effect = egroup(g).e<i>
        call TriggerExecute(egroup(g).callback)
        set i = i + 1
    endloop
    call TriggerRemoveAction(egroup(g).callback,ta)
    set ta = null
endfunction

function EGroupClear takes egroup g returns nothing
    loop
    exitwhen egroup(g).effectcount == 0
        set egroup(g).e[egroup(g).effectcount] = null
        set egroup(g).effectcount = egroup(g).effectcount - 1
    endloop
endfunction

function DestroyEGroup takes egroup g returns nothing
    call egroup(g).destroy()
endfunction

endlibrary
</i></i></i>


:banghead::banghead:
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Thanks, kingkingyyk3, but i think that's just uneccesary... But this is what i have now:
JASS:
scope SearingDash initializer init

globals
    private constant integer ABIL_ID = &#039;A000&#039; // The rawcode of the 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.
    private constant integer EFFECT_PERIODS = 48 // Here you have to do some calculation yourself.
    // 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!
endglobals

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

private struct Data
    real array ex[EFFECT_PERIODS]
    real array ey[EFFECT_PERIODS]
    integer i = 0
    real speed
    real time = 1
    unit caster
    player owner
    timer t
    integer lvl
    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.t = CreateTimer()
        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,100)
    endmethod
endstruct

private function Damage takes nothing returns real
    return I2R( Data(TempStruct).lvl) * DMG_FACTOR * 20.
endfunction

private function Filters takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit()) &gt; 0.405 and IsUnitEnemy(GetFilterUnit(), Data(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(Data(TempStruct).caster, GetEnumUnit(), Damage, true, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
endfunction

private function Damage_Period takes nothing returns boolean
    local Data d = KT_GetData()
    local integer i
    call BJDebugMsg(R2S(d.ex<i>))
    call BJDebugMsg(R2S(d.ey<i>))
    if d.time &lt; DURATION - PERIOD then
    loop
    exitwhen i &gt;= d.i
        call GroupEnumUnitsInRange(g, d.ex[d.i], d.ey[d.i], 100, Filter (function Filters))
        call ForGroup(g,function Deal_Damage)
        set i = i + 1
    endloop
    return false
    else
    return true
    endif
endfunction

private function Periodic takes nothing returns boolean
    local Data d = KT_GetData()
    if d.time &lt; DURATION - PERIOD then
        set d.time = d.time + PERIOD
        set d.ex[d.i] = GetUnitX(d.caster)
        set d.ey[d.i] = GetUnitY(d.caster)
        call KT_Add( function Damage_Period, d, DAMAGE_PERIOD)
        call TE_TimedEffect(AddSpecialEffect(EFFECT_1,d.ex[d.i],d.ey[d.i]), EFFECT_DURATION)
        set d.i = d.i+1
        return false
    else
        call d.destroy()
        return true
    endif
endfunction

private function Spell takes nothing returns nothing
    local Data D = Data.create(GetTriggerUnit())
    call SetUnitMoveSpeed(D.caster, 522)
    call SetUnitPathing(D.caster,false)
    call SetUnitVertexColor(D.caster,255,255,255,85)
    set TempStruct = D
    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)
endfunction
endscope</i></i>


And the effects and stuff are still good, but now I'm coming in to the damage part :(
And that isn't going too well XD

As you can see I've put in some debug msg there, but they aren't showing in-game :(

Any ideas why ??? :S

I put them in another one of those function (The "Periodic" one) and then it showed, so why not in the damage function ??? :(
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
It works now :

JASS:
scope SearingDash initializer init

globals
    private constant integer ABIL_ID = &#039;A000&#039; // The rawcode of the 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!
endglobals

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

private struct Data
    real speed
    real time = 1
    unit caster
    player owner
    integer lvl
    
    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)
    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 * 20.
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)
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, 100., 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 Spell takes nothing returns nothing
    local Data D = Data.create(GetTriggerUnit())
    call SetUnitMoveSpeed(D.caster, 522)
    call SetUnitPathing(D.caster,false)
    call SetUnitVertexColor(D.caster,255,255,255,85)
    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)
endfunction
endscope
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Yay... It works :D But now the damage never stops damaging :( Even when the effects and the spells waers off, it still damages where there used to be effects :S

Any ideas why and how to fix ??? :eek:
 

Komaqtion

You can change this now in User CP.
Reaction score
469
Ok, nice that you fixed that, but now it doesn't deal any damage :( Here's the code:
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!
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
    
    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)
        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 * 20.
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 takes nothing returns nothing
    local Data d
    local real x1 = GetOrderPointX()
    local real y1 = GetOrderPointY()
    local real x2 = GetUnitX(d.caster)
    local real y2 = GetUnitY(d.caster)
    local real angle = bj_RADTODEG * Atan2(y1 - y1, x1 - x2)
    local real newx = x2 + 5 * Cos(angle * bj_DEGTORAD)
    local real newy = y2 + 5 * Sin(angle * bj_DEGTORAD)
    call SetUnitX(d.caster, newx)
    call SetUnitY(d.caster, newy)
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,Abs 255 * (TRANSPARENCY / 100))
    call UnitRemoveAbility( D.caster, ATTACK_ID)
    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)
endfunction
endscope


I've now implemented BoundSentinel too, because I'm trying to do a custom movement system, since just setting it to 522 is quite boring XD questions:

Do I need to put required BoundSentinel for it to help ?? :S

How do I get the absolute value of an integer, or real...
JASS:
call SetUnitVertexColor(D.caster,255,255,255,Abs 255 * (TRANSPARENCY / 100))


This makes it completely invisible now, and I think it might be because the value becomes 216,75... can this be fixed ???

And, now the movement "system" isn't working either :( Any ideas and suggestions ??? :S
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      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