HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Spell Help 2

07-02-2006, 02:54 AM#1
emjlr3
ok so this is an aura ability

all units within a certain range take damage dependant on how far they move while they are in this range

it works sporadically, sometimes it does, sometimes it just dosn't, can anyone think of a possibly better way to do this, or why it may work sometimes and not other times

Collapse JASS:
function Trig_Ring_of_Fire_Conditions takes nothing returns boolean
    return GetLearnedSkill() == 'A04I' 
endfunction

function ROF_Effects takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local string s = GetAttTable(t)
    local unit u = GetTableUnit(s,"u")
    local unit targ = GetTableUnit(s,"targ")  
    local real x = GetTableReal(s,"x")
    local real y = GetTableReal(s,"y")
    local real dist = DistanceBetweenPointsXY(GetUnitX(targ),GetUnitY(targ),x,y)
    local real dam = dist*(.02+(.02*GetUnitAbilityLevel(u,'A04I')))  
    
    if dist>5 then
        call UnitDamageTarget(u,targ,dam,false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)
        //call TextTagUnit(R2S(dam),targ,255,255,255,255,.03,3)
    endif
    call SetTableReal(s,"x",GetUnitX(targ))
    call SetTableReal(s,"y",GetUnitY(targ))
    
    set u = null
    set targ = null
endfunction

function ROF_Filter takes nothing returns boolean
    local string s = GetAttTable(GetTriggeringTrigger())
    return IsUnitEnemy(GetTriggerUnit(),GetOwningPlayer(GetTableUnit(s,"u")))==true and GetUnitState(GetTriggerUnit(),UNIT_STATE_LIFE)>0    
endfunction

function ROF_Child takes nothing returns nothing
    local trigger trig = GetTriggeringTrigger()
    local string strig = GetAttTable(trig)
    local unit u = GetTableUnit(strig,"u")
    local unit targ = GetTriggerUnit()
    local timer t = CreateTimer()
    local string s = GetAttTable(t)
    
    call SetTableObject(s,"u",u)
    call SetTableObject(s,"targ",targ)
    call SetTableReal(s,"x",GetUnitX(targ))
    call SetTableReal(s,"y",GetUnitY(targ))
    call TimerStart(t,.05,true,function ROF_Effects)    
    loop
        exitwhen GetUnitState(targ,UNIT_STATE_LIFE)<=0 or DistanceBetweenPointsXY(GetUnitX(u),GetUnitY(u),GetUnitX(targ),GetUnitY(targ))>345.
        call TriggerSleepAction(.2)
    endloop
    call Clearst(s,t)
    
    set trig = null
    set u = null
    set targ = null
endfunction

function Trig_Ring_of_Fire_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local trigger trig = CreateTrigger()
    local string s = GetAttTable(trig)
    
    if GetUnitAbilityLevel(u,'A04I')==1 then
        call TriggerRegisterUnitInRange( trig,u,350.,null)
        call TriggerAddCondition(trig,Condition(function ROF_Filter))
        call TriggerAddAction(trig,function ROF_Child)
        call SetTableObject(s,"u",u)
    endif    
    
    set u = null
    set trig = null
endfunction

//===========================================================================
function InitTrig_Ring_of_Fire takes nothing returns nothing
    set gg_trg_Ring_of_Fire = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Ring_of_Fire, EVENT_PLAYER_HERO_SKILL )
    call TriggerAddCondition( gg_trg_Ring_of_Fire, Condition( function Trig_Ring_of_Fire_Conditions ) )
    call TriggerAddAction( gg_trg_Ring_of_Fire, function Trig_Ring_of_Fire_Actions )
endfunction

while I am at it, I tried to make this so that it only damages each unit once, but it still seems to damage units more then once, what gives?

Collapse JASS:
function Trig_Geyser_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A03R' 
endfunction

function Geyser_Child takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local string s = GetAttTable(t)
    local integer totdist = GetTableInt(s,"totdist")  
    local integer lvl = GetTableInt(s,"lvl")      
    local unit u = GetTableUnit(s,"u")
    local unit targ 
    local real dist = GetTableReal(s,"dist")
    local real ang = GetTableReal(s,"ang")    
    local real x = GetTableReal(s,"x")
    local real y = GetTableReal(s,"y")    
    local real x1
    local real y1
    local group g = CreateGroup() 
    local group damaged = CreateGroup()   
    local player p = GetOwningPlayer(u)
    
    call GroupAddGroup(GetTableGroup(s,"damaged"),damaged)
    if totdist<=dist then
        set x1 = x + totdist * Cos(ang * bj_DEGTORAD) + GetRandomReal(-25, 25 )
        set y1 = y + totdist * Sin(ang * bj_DEGTORAD) + GetRandomReal(-25, 25 )
        call DestroyEffect(AddSpecialEffect("TidalErruption.mdx",x1,y1))
        call GroupEnumUnitsInRange(g,x1,y1,120,null)
        loop
            set targ = FirstOfGroup(g)
            exitwhen targ == null
            if IsUnitEnemy(targ,p)==true and IsUnitInGroup(targ,damaged)==false then
                call UnitDamageTarget(u,targ,20+(lvl*70),false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)
                set bj_lastCreatedUnit = CreateCaster(p,x1,y1,0,'A03T',lvl)
                call IssueTargetOrder(bj_lastCreatedUnit,"slow",targ) 
                call GroupAddUnit(damaged,targ)               
            endif
            call GroupRemoveUnit(g,targ)
        endloop
        call SetTableObject(s,"damaged",damaged)
        call SetTableInt(s,"totdist",totdist+110)        
    else        
        call Clearst(s,t)
    endif       
    
    set u = null
    call DestroyGroup(g)
    call DestroyGroup(damaged)
    set g = null   
    set damaged = null 
    set p = null    
endfunction

function Trig_Geyser_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local location l = GetSpellTargetLoc()
    local integer lvl = GetUnitAbilityLevel(u,'A03R')
    local real x = GetLocationX(l)
    local real y = GetLocationY(l)
    local real x1 = GetUnitX(u)
    local real y1 = GetUnitY(u)
    local real ang = AngleBetweenPointsXY(x1,y1,x,y)
    local real dist = DistanceBetweenPointsXY(x1,y1,x,y)
    local timer t = CreateTimer()   
    local string s = GetAttTable(t) 
    
    call SetTableReal(s,"x",x1)
    call SetTableReal(s,"y",y1)
    call SetTableReal(s,"dist",dist)
    call SetTableReal(s,"ang",ang)        
    call SetTableInt(s,"totdist",50)
    call SetTableInt(s,"lvl",lvl)
    call SetTableObject(s,"u",u)
    call SetTableObject(s,"damaged",CreateGroup())
    call TimerStart(t,.1,true,function Geyser_Child)
    
    call RemoveLocation(l)
    set l = null
    set u = null
endfunction

//===========================================================================
function InitTrig_Geyser takes nothing returns nothing
    set gg_trg_Geyser = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Geyser, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Geyser, Condition( function Trig_Geyser_Conditions ) )
    call TriggerAddAction( gg_trg_Geyser, function Trig_Geyser_Actions )
endfunction
07-02-2006, 03:02 AM#2
Naakaloh
Would it not be better to simply set register the trigger as periodic event? That way you would have to worry about units entering the range to cause it to fire.

I'm not sure about the second part, but you could try creating a temporary group that contains all the units of the first group then just looping through those and removing them after dealing damage to them.
07-02-2006, 04:43 PM#3
emjlr3
i am a little confused as to ur first suggestion, and for your second, I thought that is what I did
07-02-2006, 05:28 PM#4
Naakaloh
For the first part you have:

Quote:
Collapse JASS:
    if GetUnitAbilityLevel(u,'A04I')==1 then
        call TriggerRegisterUnitInRange( trig,u,350.,null)
        call TriggerAddCondition(trig,Condition(function ROF_Filter))
        call TriggerAddAction(trig,function ROF_Child)
        call SetTableObject(s,"u",u)
    endif    

I that means that it will only run when an enemy unit comes within range of the unit u, so that might explain why sometimes it doesn't work. I assume you're trying to make a spell thats somewhat like an immolation variant. If you change TriggerRegisterUnitInRange to TriggerRegisterTimerEventPeriodic, you can just grab all the units within the radius and deal the appropriate damage to them, that way you wouldn't have to worry about this:

Quote:
Collapse JASS:
    call TimerStart(t,.05,true,function ROF_Effects)    
    loop
        exitwhen GetUnitState(targ,UNIT_STATE_LIFE)<=0 or DistanceBetweenPointsXY(GetUnitX(u),GetUnitY(u),GetUnitX(targ),GetUnitY(targ))>345.
        call TriggerSleepAction(.2)
    endloop
    call Clearst(s,t)

And you could simply have one function to call.

For the second one, sorry, I misunderstood what you wanted to do, I think I see the issue now; instead of using:

Collapse JASS:
call SetTableObject(s,"damaged",damaged)

use:

Collapse JASS:
call GroupAddGroup(damaged, GetTableObject(s,"damaged"))

At the end you destroy the local damaged, but that happens to be the same group that GetTableObject(s, "damaged) will be pointing to, so when it runs again it will return null. Doing it like this keeps the group from being destroyed, the only thing is, you'll have to be sure to create a group if one doesn't exist, and get rid of the group when everything is done.