Help improving this Spell

Zwiebelchen

You can change this now in User CP.
Reaction score
60
Hmm, this is a spell that creates a cross-shaped special effect below the feet of the caster pointing towards the selected target destination.

The spell lags heavily everytime the dummys are created and destroyed.

I know that I could make it more efficient using a struct instead of all those hashtable slots, but I think that is not the problem here. Anyone has an idea what could be the problem?

PS: The spell lags even if there is no unit in range, so it's not the damage function that causes the lag.
Also, the spell doesn't lag in singleplayer or Bnet-games without other players.

JASS:
library Crucify uses Damage, ZTS


globals
    private integer system_dummyId1 = 'h00V'
    private integer system_spellId = 'A042'
    private string system_orderId = "unloadall"
    private constant group targetGroup = CreateGroup()
    private player tplayer = null
endglobals
private function DamageTarget takes unit caster, unit target returns nothing
    local real dmg = (I2R(StatSpellpower[caster])) * 1.5 * (GetRandomReal(0.8, 1.2))
    if IsUnitType(target, UNIT_TYPE_UNDEAD) then
        set dmg = dmg*2
    endif
    call UnitDamageTargetEx(caster, target, dmg, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_DIVINE, WEAPON_TYPE_WHOKNOWS)
    call ZTS_ModifyThreat(caster, target, dmg*0.5, true)
endfunction
private function GroupFilter takes nothing returns boolean
    return (GetUnitTypeId(GetFilterUnit())!=system_dummyId1) and IsUnitEnemy(GetFilterUnit(), tplayer)
endfunction
//-----------------------------------------------------------------------------
private function RotMatrixX takes real x, real y, real angle returns real
    return x*Cos(angle)-y*Sin(angle)
endfunction
private function RotMatrixY takes real x, real y, real angle returns real
    return x*Sin(angle)+y*Cos(angle)
endfunction

private function Tick takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer parentKey = GetHandleId(t)
    local integer state = LoadInteger(TimerHash, parentKey, 2)
    local integer drawMax
    local integer i = 6
    local real angle = LoadReal(TimerHash, parentKey, 5)
    local unit caster = LoadUnitHandle(TimerHash, parentKey, 0)
    local unit tempUnit
    local real tempUnitX
    local real tempUnitY
    local real length
    local real width
    local real casterX = LoadReal(TimerHash, parentKey, 3)
    local real casterY = LoadReal(TimerHash, parentKey, 4)
    local boolean channeling = false
    
    call RecalcStats(caster)
    if (OrderId2String(GetUnitCurrentOrder(caster))==system_orderId) then
        set channeling = true
    endif
    if(channeling) then
        call SaveInteger(TimerHash, parentKey, 2, state+1)
        if(state==0) then
            set drawMax = 135
            set length = 300
            set width = 50
        elseif(state==1) then
            set drawMax = 111
            set length = 250
            set width = 50
        elseif(state==2) then
            set drawMax = 87
            set length = 200
            set width = 50
        elseif(state==3) then
            set drawMax = 63
            set length = 150
            set width = 50
        endif
        
        loop
            exitwhen i>=drawMax
            call KillUnit(CreateUnit(GetOwningPlayer(caster), system_dummyId1, LoadReal(TimerHash, parentKey, i),LoadReal(TimerHash, parentKey, i+1), 0.0))
            set i=i+2
        endloop
        set tplayer = GetOwningPlayer(caster)
        call GroupEnumUnitsInRange(targetGroup, casterX, casterY, 300, Condition(function GroupFilter))
        set tempUnit=FirstOfGroup(targetGroup)
        set tplayer = null
        loop
            exitwhen tempUnit==null
            set tempUnitX = RotMatrixX(GetUnitX(tempUnit)-casterX, GetUnitY(tempUnit)-casterY, angle*(-1))
            set tempUnitY = RotMatrixY(GetUnitX(tempUnit)-casterX, GetUnitY(tempUnit)-casterY, angle*(-1))
            if((((-1)*width<=tempUnitX)and(tempUnitX<=width)and((-1)*length<=tempUnitY)and(tempUnitY<=length)) or (((-1)*width<=tempUnitY)and(tempUnitY<=width)and((-1)*length<=tempUnitX)and(tempUnitX<=length))) then
                call DamageTarget(caster, tempUnit)
            endif
            call GroupRemoveUnit(targetGroup, tempUnit)
            set tempUnit=FirstOfGroup(targetGroup)
        endloop
    
        if(state==0) then
            call TimerStart(t, 0.7, false, function Tick)
        elseif(state==1) then
            call TimerStart(t, 0.7, false, function Tick)
        elseif(state==2) then
            call TimerStart(t, 0.7, false, function Tick)
        else
            call FlushChildHashtable(TimerHash, parentKey)
            call DestroyTimer(t)
        endif
    else
        call FlushChildHashtable(TimerHash, parentKey)
        call DestroyTimer(t)
    endif
    set t=null
    set caster = null
    set tempUnit = null
endfunction

function Crucify takes unit caster, unit target returns nothing
    local timer t = CreateTimer()
    local integer parentKey = GetHandleId(t)
    local real targetX = GetUnitX(target)
    local real targetY = GetUnitY(target)
    local real casterX = GetUnitX(caster)
    local real casterY = GetUnitY(caster)
    local real angle = Atan2(targetY-casterY,targetX-casterX)
    local integer i
    local integer childKey = 0

    call SaveUnitHandle(TimerHash, parentKey, 0, caster)
    call SaveUnitHandle(TimerHash, parentKey, 1, target)
    call SaveInteger(TimerHash, parentKey, 2, 0)
    call SaveReal(TimerHash, parentKey, 3, casterX)
    call SaveReal(TimerHash, parentKey, 4, casterY)
    call SaveReal(TimerHash, parentKey, 5, angle)
    //middle:
    call SaveReal(TimerHash, parentKey, 6, casterX)
    call SaveReal(TimerHash, parentKey, 7, casterY)
    call SaveReal(TimerHash, parentKey, 8, casterX+RotMatrixX(25,25,angle))
    call SaveReal(TimerHash, parentKey, 9, casterY+RotMatrixY(25,25,angle))
    call SaveReal(TimerHash, parentKey, 10, casterX+RotMatrixX(25,-25,angle))
    call SaveReal(TimerHash, parentKey, 11, casterY+RotMatrixY(25,-25,angle))
    call SaveReal(TimerHash, parentKey, 12, casterX+RotMatrixX(-25,25,angle))
    call SaveReal(TimerHash, parentKey, 13, casterY+RotMatrixY(-25,25,angle))
    call SaveReal(TimerHash, parentKey, 14, casterX+RotMatrixX(-25,-25,angle))
    call SaveReal(TimerHash, parentKey, 15, casterY+RotMatrixY(-25,-25,angle))
    set childKey=16
    //row1:
    set i=0
    loop
        exitwhen i==4
        call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(50,0,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(50,0,angle+i*bj_PI/2))
        set childKey=childKey+1
        set i=i+1
    endloop //childkey == 23
    //row2:
    set i=0
    loop
        exitwhen i==4
        call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(75,25,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(75,25,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(75,-25,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(75,-25,angle+i*bj_PI/2))
        set childKey=childKey+1
        set i=i+1
    endloop //childkey == 39
    //row3:
    set i=0
    loop
        exitwhen i==4
        call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(100,0,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(100,0,angle+i*bj_PI/2))
        set childKey=childKey+1
        set i=i+1
    endloop //childkey == 47
    //row4:
    set i=0
    loop
        exitwhen i==4
        call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(125,25,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(125,25,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(125,-25,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(125,-25,angle+i*bj_PI/2))
        set childKey=childKey+1
        set i=i+1
    endloop //childkey == 63
    //row5:
    set i=0
    loop
        exitwhen i==4
        call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(150,0,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(150,0,angle+i*bj_PI/2))
        set childKey=childKey+1
        set i=i+1
    endloop //childkey == 71
    //row6:
    set i=0
    loop
        exitwhen i==4
        call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(175,25,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(175,25,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(175,-25,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(175,-25,angle+i*bj_PI/2))
        set childKey=childKey+1
        set i=i+1
    endloop //childkey == 87
    //row7:
    set i=0
    loop
        exitwhen i==4
        call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(200,0,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(200,0,angle+i*bj_PI/2))
        set childKey=childKey+1
        set i=i+1
    endloop //childkey == 95
    //row8:
    set i=0
    loop
        exitwhen i==4
        call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(225,25,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(225,25,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(225,-25,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(225,-25,angle+i*bj_PI/2))
        set childKey=childKey+1
        set i=i+1
    endloop //childkey == 111
    //row9:
    set i=0
    loop
        exitwhen i==4
        call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(250,0,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(250,0,angle+i*bj_PI/2))
        set childKey=childKey+1
        set i=i+1
    endloop //childkey == 119
    //row10:
    set i=0
    loop
        exitwhen i==4
        call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(250,40,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(250,40,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(250,-40,angle+i*bj_PI/2))
        set childKey=childKey+1
        call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(250,-40,angle+i*bj_PI/2))
        set childKey=childKey+1
        set i=i+1
    endloop //childkey == 135
    call TimerStart(t, 0.0, false, function Tick)
    set t = null
endfunction

endlibrary
 
don't get why you can't use just one loop for every i = i + 1

is the same thing every loop :s
 
JASS:
        loop
            exitwhen i>=drawMax
            call KillUnit(CreateUnit(GetOwningPlayer(caster), system_dummyId1, LoadReal(TimerHash, parentKey, i),LoadReal(TimerHash, parentKey, i+1), 0.0))
            set i=i+2
        endloop


Lol!

67 times CreateUnit, GetOwningPlayer, LoadReal, LoadReal, i+1.
And where's the problem? o_O

I agree that GetOwningPlayer(caster) should be a variable to improve performance, but I don't see how I should avoid the unit creation and the checking of the spawn coordinates?
don't get why you can't use just one loop for every i = i + 1

is the same thing every loop :s
No it's not. The coordinates are always different.
 
Use DestroyEffect(AddSpecialEffect... instead?
Unit creation is taxing.
I can't, as the special effects do not allow Z coordinates (at least I haven't found out how). The problem with this spell is, that only units can have a certain flyHeight.
 
Hmm, this is a spell that creates a cross-shaped special effect below the feet of the caster pointing towards the selected target destination.

The spell lags heavily everytime the dummys are created and destroyed.

I know that I could make it more efficient using a struct instead of all those hashtable slots, but I think that is not the problem here. Anyone has an idea what could be the problem?

PS: The spell lags even if there is no unit in range, so it's not the damage function that causes the lag.
Also, the spell doesn't lag in singleplayer or Bnet-games without other players.

library Crucify uses Damage, ZTS


globals
private integer system_dummyId1 = 'h00V'
private integer system_spellId = 'A042'
private string system_orderId = "unloadall"
private constant group targetGroup = CreateGroup()
private player tplayer = null
endglobals
private function DamageTarget takes unit caster, unit target returns nothing
local real dmg = (I2R(StatSpellpower[caster])) * 1.5 * (GetRandomReal(0.8, 1.2))
if IsUnitType(target, UNIT_TYPE_UNDEAD) then
set dmg = dmg*2
endif
call UnitDamageTargetEx(caster, target, dmg, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_DIVINE, WEAPON_TYPE_WHOKNOWS)
call ZTS_ModifyThreat(caster, target, dmg*0.5, true)
endfunction
private function GroupFilter takes nothing returns boolean
return (GetUnitTypeId(GetFilterUnit())!=system_dummyId1) and IsUnitEnemy(GetFilterUnit(), tplayer)
endfunction
//-----------------------------------------------------------------------------
private function RotMatrixX takes real x, real y, real angle returns real
return x*Cos(angle)-y*Sin(angle)
endfunction
private function RotMatrixY takes real x, real y, real angle returns real
return x*Sin(angle)+y*Cos(angle)
endfunction

private function Tick takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer parentKey = GetHandleId(t)
local integer state = LoadInteger(TimerHash, parentKey, 2)
local integer drawMax
local integer i = 6
local real angle = LoadReal(TimerHash, parentKey, 5)
local unit caster = LoadUnitHandle(TimerHash, parentKey, 0)
local unit tempUnit
local real tempUnitX
local real tempUnitY
local real length
local real width
local real casterX = LoadReal(TimerHash, parentKey, 3)
local real casterY = LoadReal(TimerHash, parentKey, 4)
local boolean channeling = false

call RecalcStats(caster)
if (OrderId2String(GetUnitCurrentOrder(caster))==system_orderId) then
set channeling = true
endif
if(channeling) then
call SaveInteger(TimerHash, parentKey, 2, state+1)
if(state==0) then
set drawMax = 135
set length = 300
set width = 50
elseif(state==1) then
set drawMax = 111
set length = 250
set width = 50
elseif(state==2) then
set drawMax = 87
set length = 200
set width = 50
elseif(state==3) then
set drawMax = 63
set length = 150
set width = 50
endif

loop
exitwhen i>=drawMax
call KillUnit(CreateUnit(GetOwningPlayer(caster), system_dummyId1, LoadReal(TimerHash, parentKey, i),LoadReal(TimerHash, parentKey, i+1), 0.0))
set i=i+2
endloop
set tplayer = GetOwningPlayer(caster)
call GroupEnumUnitsInRange(targetGroup, casterX, casterY, 300, Condition(function GroupFilter))
set tempUnit=FirstOfGroup(targetGroup)
set tplayer = null
loop
exitwhen tempUnit==null
set tempUnitX = RotMatrixX(GetUnitX(tempUnit)-casterX, GetUnitY(tempUnit)-casterY, angle*(-1))
set tempUnitY = RotMatrixY(GetUnitX(tempUnit)-casterX, GetUnitY(tempUnit)-casterY, angle*(-1))
if((((-1)*width<=tempUnitX)and(tempUnitX<=width)and((-1)*length<=tempUnitY)and(tempUnitY<=length)) or (((-1)*width<=tempUnitY)and(tempUnitY<=width)and((-1)*length<=tempUnitX)and(tempUnitX<=length))) then
call DamageTarget(caster, tempUnit)
endif
call GroupRemoveUnit(targetGroup, tempUnit)
set tempUnit=FirstOfGroup(targetGroup)
endloop

if(state==0) then
call TimerStart(t, 0.7, false, function Tick)
elseif(state==1) then
call TimerStart(t, 0.7, false, function Tick)
elseif(state==2) then
call TimerStart(t, 0.7, false, function Tick)
else
call FlushChildHashtable(TimerHash, parentKey)
call DestroyTimer(t)
endif
else
call FlushChildHashtable(TimerHash, parentKey)
call DestroyTimer(t)
endif
set t=null
set caster = null
set tempUnit = null
endfunction

function Crucify takes unit caster, unit target returns nothing
local timer t = CreateTimer()
local integer parentKey = GetHandleId(t)
local real targetX = GetUnitX(target)
local real targetY = GetUnitY(target)
local real casterX = GetUnitX(caster)
local real casterY = GetUnitY(caster)
local real angle = Atan2(targetY-casterY,targetX-casterX)
local integer i
local integer childKey = 0

call SaveUnitHandle(TimerHash, parentKey, 0, caster)
call SaveUnitHandle(TimerHash, parentKey, 1, target)
call SaveInteger(TimerHash, parentKey, 2, 0)
call SaveReal(TimerHash, parentKey, 3, casterX)
call SaveReal(TimerHash, parentKey, 4, casterY)
call SaveReal(TimerHash, parentKey, 5, angle)
//middle:
call SaveReal(TimerHash, parentKey, 6, casterX)
call SaveReal(TimerHash, parentKey, 7, casterY)
call SaveReal(TimerHash, parentKey, 8, casterX+RotMatrixX(25,25,angle))
call SaveReal(TimerHash, parentKey, 9, casterY+RotMatrixY(25,25,angle))
call SaveReal(TimerHash, parentKey, 10, casterX+RotMatrixX(25,-25,angle))
call SaveReal(TimerHash, parentKey, 11, casterY+RotMatrixY(25,-25,angle))
call SaveReal(TimerHash, parentKey, 12, casterX+RotMatrixX(-25,25,angle))
call SaveReal(TimerHash, parentKey, 13, casterY+RotMatrixY(-25,25,angle))
call SaveReal(TimerHash, parentKey, 14, casterX+RotMatrixX(-25,-25,angle))
call SaveReal(TimerHash, parentKey, 15, casterY+RotMatrixY(-25,-25,angle))
set childKey=16
//row1:
set i=0
loop
exitwhen i==4
call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(50,0,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(50,0,angle+i*bj_PI/2))
set childKey=childKey+1
set i=i+1
endloop //childkey == 23
//row2:
set i=0
loop
exitwhen i==4
call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(75,25,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(75,25,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(75,-25,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(75,-25,angle+i*bj_PI/2))
set childKey=childKey+1
set i=i+1
endloop //childkey == 39
//row3:
set i=0
loop
exitwhen i==4
call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(100,0,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(100,0,angle+i*bj_PI/2))
set childKey=childKey+1
set i=i+1
endloop //childkey == 47
//row4:
set i=0
loop
exitwhen i==4
call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(125,25,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(125,25,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(125,-25,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(125,-25,angle+i*bj_PI/2))
set childKey=childKey+1
set i=i+1
endloop //childkey == 63
//row5:
set i=0
loop
exitwhen i==4
call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(150,0,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(150,0,angle+i*bj_PI/2))
set childKey=childKey+1
set i=i+1
endloop //childkey == 71
//row6:
set i=0
loop
exitwhen i==4
call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(175,25,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(175,25,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(175,-25,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(175,-25,angle+i*bj_PI/2))
set childKey=childKey+1
set i=i+1
endloop //childkey == 87
//row7:
set i=0
loop
exitwhen i==4
call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(200,0,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(200,0,angle+i*bj_PI/2))
set childKey=childKey+1
set i=i+1
endloop //childkey == 95
//row8:
set i=0
loop
exitwhen i==4
call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(225,25,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(225,25,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(225,-25,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(225,-25,angle+i*bj_PI/2))
set childKey=childKey+1
set i=i+1
endloop //childkey == 111
//row9:
set i=0
loop
exitwhen i==4
call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(250,0,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(250,0,angle+i*bj_PI/2))
set childKey=childKey+1
set i=i+1
endloop //childkey == 119
//row10:
set i=0
loop
exitwhen i==4
call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(250,40,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(250,40,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterX+RotMatrixX(250,-40,angle+i*bj_PI/2))
set childKey=childKey+1
call SaveReal(TimerHash, parentKey, childKey, casterY+RotMatrixY(250,-40,angle+i*bj_PI/2))
set childKey=childKey+1
set i=i+1
endloop //childkey == 135
call TimerStart(t, 0.0, false, function Tick)
set t = null
endfunction

endlibrary
i just wanted to see it without the silly jass scrolly box.

hmm...the description of what the spell does is kindof hard to understand...
i think i sortof know what you're doing...
I would like to see the Damage and ZTS libraries...and want to know what models you're using for the dummies.

is your spell not kindof like this one?


scope SearingLight initializer I
//! textmacro searinglight takes reala, realb
set u = CreateUnit(p, SpiritWalker_SearingLightBeam, ux + 400.00 * Cos($reala$ * bj_DEGTORAD), uy + 400.00 * Sin($reala$ * bj_DEGTORAD), $realb$)
call UnitApplyTimedLife(u, 'BTLF', 3.0)
//! endtextmacro
private function fa takes nothing returns boolean
local unit u = GetTriggerUnit()
local player p = GetOwningPlayer(u)
local real ux = GetUnitX(u)
local real uy = GetUnitY(u)
//! runtextmacro searinglight("45.00","270.00")
//! runtextmacro searinglight("45.00","180.00")
//! runtextmacro searinglight("45.00","225.00")
//! runtextmacro searinglight("135.00","270.00")
//! runtextmacro searinglight("135.00","0.00")
//! runtextmacro searinglight("135.00","315.00")
//! runtextmacro searinglight("225.00","90.00")
//! runtextmacro searinglight("225.00","0.00")
//! runtextmacro searinglight("225.00","45.00")
//! runtextmacro searinglight("315.00","90.00")
//! runtextmacro searinglight("315.00","180.00")
//! runtextmacro searinglight("315.00","135.00")
set u = null
return false
endfunction
public function I takes nothing returns nothing
call GT_AddStartsEffectAction(function fa,SpiritWalker_SearingLight)
call XE_PreloadAbility(SpiritWalker_SearingLight)
endfunction
endscope

this spell is not a cross effect...and i have no idea what color you want it to be(it's bright like healing wave or shockwave)...but it does draw a box and an ex...if you modify it, you might be able to come up with something like what you need for your spell...and i don't think it lags...

oh and...you should probably use textmacro

yeah this spell doesn't use timers...so it's an instant effect, basically...if you need the timers then your spell is more complicated than your description implies...either you need to be more descriptive or you have some useless stuff in your trigger.
 

After testing this method intensively, I must recommend against it. It seems to build up lag that never goes away, which does not occur with the create/remove destructable lines omitted. :thdown:

[edit] But it's negligible unless run thousands of times.
 
I would like to see the Damage and ZTS libraries...and want to know what models you're using for the dummies.
The damage and ZTS libraries are fine. Its not the damage part that is lagging the spell, as it also lags with no units affected at all.

is your spell not kindof like this one?

this spell is not a cross effect...and i have no idea what color you want it to be(it's bright like healing wave or shockwave)...but it does draw a box and an ex...if you modify it, you might be able to come up with something like what you need for your spell...and i don't think it lags...
It does exactly the same as I do. Having fixed coordinates and applying a transformation matrix to them.

oh and...you should probably use textmacro
This has no effect on runtime. Textmacros just save lines of code, as Textmacros get replaced when compiling.

yeah this spell doesn't use timers...so it's an instant effect, basically...if you need the timers then your spell is more complicated than your description implies...either you need to be more descriptive or you have some useless stuff in your trigger.
Its a channeled spell. It has 4 pulses, creating a shrinking cross.

The model I used for the dummies is the one of the Divine Shield of the Paladin.
 
Its a channeled spell. It has 4 pulses, creating a shrinking cross.
oh...in that case...check this out...

not sure how similiar it is to your spell...but it does use pulses and the rings get smaller

whoever made this spell made it on a water elemental...
and they didn't put their name in comments anywhere.
JASS:

constant function HR_Ring_Interval takes nothing returns real
    return 0.35      //The raw code of the ability &quot;Hydro Rings&quot;
endfunction

constant function HR_Damage_Base takes nothing returns real
    return 30.0      //The base damage for the spell
endfunction

constant function HR_AoE takes nothing returns real
    return 200.0      //The AoE of each explosion
endfunction

constant function HR_Ring1_Explosion_Offset takes nothing returns real
    return 350.0      //The explosion offset in the 1st ring
endfunction

constant function HR_Ring2_Explosion_Offset takes nothing returns real
    return 250.0      //The explosion offset in the 2nd ring
endfunction

constant function HR_Ring3_Explosion_Offset takes nothing returns real
    return 150.0      //The explosion offset in the 3rd ring
endfunction

constant function HR_Ring1_Explosion_Count takes nothing returns integer
    return 10         //The amount of water explosions in the 1st ring
endfunction

constant function HR_Ring2_Explosion_Count takes nothing returns integer
    return 8          //The amount of water explosions in the 2nd ring
endfunction 

constant function HR_Ring3_Explosion_Count takes nothing returns integer
    return 6          //The amount of water explosions in the 3rd ring
endfunction

constant function HR_Ability_ID takes nothing returns integer
    return &#039;A08D&#039;     //The raw code of the ability &quot;Hydro Rings&quot;
endfunction

constant function HR_Dummy_Unit_ID takes nothing returns integer
    return &#039;h01D&#039;     //The raw code of the unit &quot;Hydro Rings Dummy&quot;
endfunction

function HR_Filter takes nothing returns boolean
    return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit())) and GetWidgetLife(GetFilterUnit()) &gt; 0.405
endfunction

function HR_Actions takes nothing returns nothing    
    local unit u = GetTriggerUnit()
    local location l = GetSpellTargetLoc()
    local real dmg = GetUnitAbilityLevel(u, HR_Ability_ID()) * HR_Damage_Base()
    local integer i = 0
    local group g = CreateGroup()
    local boolexpr b = Condition(function HR_Filter)
    local unit p
    local location ll
   
    loop
        exitwhen i &gt; HR_Ring1_Explosion_Count()    
        set ll = PolarProjectionBJ(l, HR_Ring1_Explosion_Offset(), 360.00/HR_Ring1_Explosion_Count() * i)
        call CreateUnitAtLoc(GetOwningPlayer(u), HR_Dummy_Unit_ID(), ll, 0)
        call GroupEnumUnitsInRangeOfLoc(g, ll, HR_AoE(), b)
        loop
            set p = FirstOfGroup(g)
            exitwhen p == null
            call GroupRemoveUnit(g, p)
            call UnitDamageTarget(u, p, dmg, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
        endloop
        call RemoveLocation(ll)
        set i = i + 1
    endloop

    call PolledWait(HR_Ring_Interval())    
    set i = 0 

    loop
        exitwhen i &gt; HR_Ring2_Explosion_Count()    
        set ll = PolarProjectionBJ(l, HR_Ring2_Explosion_Offset(), 360.00/HR_Ring2_Explosion_Count() * i)
        call CreateUnitAtLoc(GetOwningPlayer(u), HR_Dummy_Unit_ID(), ll, 0)
        call GroupEnumUnitsInRangeOfLoc(g, ll, HR_AoE(), b)
        loop
            set p = FirstOfGroup(g)
            exitwhen p == null
            call GroupRemoveUnit(g, p)
            call UnitDamageTarget(u, p, dmg, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
        endloop
        call RemoveLocation(ll)
        set i = i + 1
    endloop  
 
    call PolledWait(HR_Ring_Interval())    
    set i = 0 
    
    loop
        exitwhen i &gt; HR_Ring3_Explosion_Count()    
        set ll = PolarProjectionBJ(l, HR_Ring3_Explosion_Offset(), 360.00/HR_Ring3_Explosion_Count() * i)
        call CreateUnitAtLoc(GetOwningPlayer(u), HR_Dummy_Unit_ID(), ll, 0)
        call GroupEnumUnitsInRangeOfLoc(g, ll, HR_AoE(), b)
        loop
            set p = FirstOfGroup(g)
            exitwhen p == null
            call GroupRemoveUnit(g, p)
            call UnitDamageTarget(u, p, dmg, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
        endloop
        call RemoveLocation(ll)
        set i = i + 1
    endloop 

    call RemoveLocation(l)
    call DestroyGroup(g)
    call DestroyBoolExpr(b)

    set u = null
    set l = null
    set ll = null
    set g = null
    set b = null
endfunction

function HR_Cond takes nothing returns boolean
    return GetSpellAbilityId() == HR_Ability_ID()    
endfunction

function InitTrig_Hydro_Rings takes nothing returns nothing
    set gg_trg_Hydro_Rings = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Hydro_Rings, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_Hydro_Rings, Condition(function HR_Cond))
    call TriggerAddAction(gg_trg_Hydro_Rings, function HR_Actions)
endfunction
 
This is not really more effective considering that this spell is circular shape and circular is always easy to do as it doesnt require real polar projection and pre-form coordinates.

You miss the point of this thread.
 
use global variable instead function, more readable and fast <i think> :nuts:
 
it's not my spell...
and it has pulses in it. you said you're using pulses...so i just showed you a spell with pulses. if the spell is junk, fine...just say that. i'm just trying to compare what you were doing with what some other spellmaker guy was doing.
 
Errr ... this thread is about improving my spell, not his one, though his one is awfully triggered, I agree.
For the performance improvement, use struct.
 
You know using a custom model instead of 25 dummy units is probably the best solution.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    News portal has been retired. Main page of site goes to Headline News forum now
  • The Helper The Helper:
    I am working on getting access to the old news portal under a different URL for those that would rather use that for news before we get a different news view.
  • Ghan Ghan:
    Easily done
    +1
  • The Helper The Helper:
    https://www.thehelper.net/pages/news/ is a link to the old news portal - i will integrate it into the interface somewhere when i figure it out
  • Ghan Ghan:
    Need to try something
  • Ghan Ghan:
    Hopefully this won't cause problems.
  • Ghan Ghan:
    Hmm
  • Ghan Ghan:
    I have converted the Headline News forum to an Article type forum. It will now show the top 20 threads with more detail of each thread.
  • Ghan Ghan:
    See how we like that.
  • The Helper The Helper:
    I do not see a way to go past the 1st page of posts on the forum though
  • The Helper The Helper:
    It is OK though for the main page to open up on the forum in the view it was before. As long as the portal has its own URL so it can be viewed that way I do want to try it as a regular forum view for a while
  • Ghan Ghan:
    Yeah I'm not sure what the deal is with the pagination.
  • Ghan Ghan:
    It SHOULD be there so I think it might just be an artifact of having an older style.
  • Ghan Ghan:
    I switched it to a "Standard" article forum. This will show the thread list like normal, but the threads themselves will have the first post set up above the rest of the "comments"
  • The Helper The Helper:
    I don't really get that article forum but I think it is because I have never really seen it used on a multi post thread
  • Ghan Ghan:
    RpNation makes more use of it right now as an example: https://www.rpnation.com/news/
  • The Helper The Helper:
  • The Helper The Helper:
    What do you think Tom?
  • tom_mai78101 tom_mai78101:
    I will have to get used to this.
  • tom_mai78101 tom_mai78101:
    The latest news feed looks good

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top