HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Local timer and Projectile Problems

03-20-2008, 03:05 PM#1
Castlemaster
I created two projectile spells that do similiar actions. By projectile I mean I create a unit that moves in a strait line until it hits something.

Living Flame: Slow moving projectile that deals AoE damage

Trigger:
Collapse JASS:
function Trig_Living_Flame_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A00A' 
endfunction

function LFEnemyCheck takes nothing returns boolean
    return (IsUnitAlly(GetFilterUnit(),Player(11)))
endfunction

function LivingFlameMovement takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local real angle = GetAttachedReal(t,"angle")*bj_DEGTORAD
    local unit u = GetAttachedUnit(t,"flame")
    local real x = GetUnitX(u)+Cos(angle)*5
    local real y = GetUnitY(u)+Sin(angle)*5
    local real xorigin = GetAttachedReal(t,"X")
    local real yorigin = GetAttachedReal(t,"Y")
    local real xdist = x-xorigin
    local real ydist = y-yorigin
    local real dist = SquareRoot(xdist*xdist+ydist*ydist)
    local group g = CreateGroup()
    local real level = GetUnitAbilityLevel(udg_Elementalist,'A00A')
    local real damage = level*45
    local effect e
    local unit target 
    local boolexpr cond = Condition(function LFEnemyCheck)
    //Explodes Projectile after travelling 1000
    if dist > 1000 then
        set e = AddSpecialEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", x, y)
        call SetUnitInvulnerable(u,false)
        call SetWidgetLife(u,0)
        if (level <= 2) and (udg_LivingFlameDamageBonus > 1.5) then
            set udg_LivingFlameDamageBonus = 1.5
        elseif (level == 3 or level == 4) and (udg_LivingFlameDamageBonus > 2) then
            set udg_LivingFlameDamageBonus = 2
        elseif (level ==5) and (udg_LivingFlameDamageBonus > 2.5) then
            set udg_LivingFlameDamageBonus = 2.5
        endif
        call UnitDamagePoint(u,0,200,x,y,damage*udg_LivingFlameDamageBonus,true,false,ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
        set udg_LivingFlameFrost = false
        set udg_LivingFlameDamageBonus = 1
        call DestroyTimer(t)
    endif
    call SetUnitX(u,x)
    call SetUnitY(u,y)
    //Finds if there are nearby enemy units before exploding
    call GroupEnumUnitsInRange(g,x,y,100,cond)
    set target = FirstOfGroup(g)
    if target != null then
        set e = AddSpecialEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", x, y)
        call SetUnitInvulnerable(u,false)
        call SetWidgetLife(u,0)
        // This is an "enhancement" system that increases damage based on other factors. Shouldn't affect the spell
        if (level <= 2) and (udg_LivingFlameDamageBonus > 1.5) then
            set udg_LivingFlameDamageBonus = 1.5
        elseif (level == 3 or level == 4) and (udg_LivingFlameDamageBonus > 2) then
            set udg_LivingFlameDamageBonus = 2
        elseif (level ==5) and (udg_LivingFlameDamageBonus > 2.5) then
            set udg_LivingFlameDamageBonus = 2.5
        endif
        call UnitDamagePoint(u,0,200,x,y,damage*udg_LivingFlameDamageBonus,true,false,ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
        //This spell affects units with a specific buff. Should not affect the spell
        if GetUnitAbilityLevel(target,'B00A')>0 then
            call UnitRemoveBuffBJ('B00A',target)
            call SetUnitInvulnerable(target,false)
            call DummyCasterUnitTarget(udg_Elementalist,target,x,y,'A00W','A00S',"frostnova")        
        endif
        //This portion indicates the spell has been enhanced by Frost Shards. For some reason this part is the one offsetting the other projectiles
        if udg_LivingFlameFrost == true then
            call DummyCasterUnitTarget(udg_Elementalist,target,x,y,'A047','A02H',"frostnova")
            call DisplayTextToForce( GetPlayersAll(), "TRIGSTR_2524" )
        endif
        set udg_LivingFlameFrost = false
        set udg_LivingFlameDamageBonus = 1
        call DestroyTimer(t)
    endif
//    if udg_LivingFlameFrost == true then
//        set e = AddSpecialEffect("Doodads\\Cinematic\\TownBurningFireEmitterBlue\\TownBurningFireEmitterBlue.mdl", x, y)
//    endif
    set t = null
    set u = null
    call DestroyGroup(g)
    set g = null
    set target = null
    call DestroyEffect(e)
    set e = null
endfunction

function Trig_Living_Flame_Actions takes nothing returns nothing
    local location targetloc = GetSpellTargetLoc()
    local location casterloc = GetUnitLoc(GetTriggerUnit())
    local real angle = AngleBetweenPoints(casterloc,targetloc)
    local real x = GetLocationX(casterloc)+Cos(angle*bj_DEGTORAD)*100
    local real y = GetLocationY(casterloc)+Sin(angle*bj_DEGTORAD)*100
    local unit u = CreateUnit(GetOwningPlayer(GetTriggerUnit()),'o00C',x,y,angle)
    local timer t = CreateTimer()
    call SetUnitInvulnerable(u,true)
    call AttachObject(t,"flame",u)
    call AttachReal(t,"angle",angle)
    call AttachReal(t,"X",x)
    call AttachReal(t,"Y",y)
    call TimerStart(t, 0.05, true, function LivingFlameMovement)
    call RemoveLocation(targetloc)
    call RemoveLocation(casterloc)
    set targetloc = null
    set casterloc = null
    set u = null
    set t = null
endfunction

//===========================================================================
function InitTrig_Living_Flame takes nothing returns nothing
    set gg_trg_Living_Flame = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Living_Flame, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Living_Flame, Condition( function Trig_Living_Flame_Conditions ) )
    call TriggerAddAction( gg_trg_Living_Flame, function Trig_Living_Flame_Actions )
endfunction

Frost Shard: Fast moving projectile that deals single target damage and stun

Trigger:
Collapse JASS:
function Trig_Frost_Shards_Conditions takes nothing returns boolean
    return (GetSpellAbilityId() == 'A02H')
endfunction

function FrostShardFilter takes nothing returns boolean
    return (GetUnitTypeId(GetFilterUnit()) == 'o00C')
endfunction

function FrostShardEnemyCheck takes nothing returns boolean
    return (IsUnitAlly(GetFilterUnit(),Player(11)))
endfunction

function FrostShardMovement takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local real angle = GetAttachedReal(t,"angle")*bj_DEGTORAD
    local unit u = GetAttachedUnit(t,"shard")
    local real x = GetUnitX(u)+Cos(angle)*10
    local real y = GetUnitY(u)+Sin(angle)*10
    local real xorigin = GetAttachedReal(t,"X")
    local real yorigin = GetAttachedReal(t,"Y")
    local real xdist = x-xorigin
    local real ydist = y-yorigin
    local real dist = SquareRoot(xdist*xdist+ydist*ydist)
    local group g = CreateGroup()
    local unit target 
    local boolexpr cond = Condition(function FrostShardFilter)
    //Destroys the projectile after a certain distance. Should not affect the spell
    if dist > 1500 then
        call SetUnitInvulnerable(u,false)
        call SetWidgetLife(u,0)
        call DestroyTimer(t)
    endif
    call SetUnitX(u,x)
    call SetUnitY(u,y)
    call GroupEnumUnitsInRange(g,x,y,100,cond)
    //Looks for a nearby Living Flame, if one is nearby it sets udg_LivingFlameFrost = true and destroys the projectile
    if FirstOfGroup(g) != null then
        call SetUnitInvulnerable(u,false)
        call SetWidgetLife(u,0)
//        call AddSpecialEffectTarget("Doodads\\Cinematic\\TownBurningFireEmitterBlue\\TownBurningFireEmitterBlue.mdl",FirstOfGroup(g),"origin")
        set udg_LivingFlameFrost = true
    endif
    set cond = Condition(function FrostShardEnemyCheck)
    call GroupEnumUnitsInRange(g,x,y,50,cond)
    if FirstOfGroup(g) != null then
        set target = FirstOfGroup(g) 
        call SetUnitInvulnerable(u,false)
        call SetWidgetLife(u,0)
        call DummyCasterUnitTarget(udg_Elementalist,target,x,y,'A045','A02H',"thunderbolt")
        call DestroyTimer(t)
    endif 
    set t = null
    set u = null
    call DestroyGroup(g)
    set g = null
    set target = null
endfunction
    
function Trig_Frost_Shards_Actions takes nothing returns nothing
    local location targetloc = GetSpellTargetLoc()
    local location casterloc = GetUnitLoc(GetTriggerUnit())
    local real angle = AngleBetweenPoints(casterloc,targetloc)
    local real x = GetLocationX(casterloc)+Cos(angle*bj_DEGTORAD)*100
    local real y = GetLocationY(casterloc)+Sin(angle*bj_DEGTORAD)*100
    local unit u = CreateUnit(GetOwningPlayer(GetTriggerUnit()),'o00B',x,y,angle)
    local timer t = CreateTimer()
    call SetUnitInvulnerable(u,true)
    call AttachObject(t,"shard",u)
    call AttachReal(t,"angle",angle)
    call AttachReal(t,"X",x)
    call AttachReal(t,"Y",y)
    call TimerStart(t, 0.02, true, function FrostShardMovement)
    call RemoveLocation(targetloc)
    call RemoveLocation(casterloc)
    set targetloc = null
    set casterloc = null
    set u = null
    set t = null
endfunction

//===========================================================================
function InitTrig_Frost_Shard takes nothing returns nothing
    set gg_trg_Frost_Shard = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Frost_Shard, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Frost_Shard, Condition( function Trig_Frost_Shards_Conditions ) )
    call TriggerAddAction( gg_trg_Frost_Shard, function Trig_Frost_Shards_Actions )
endfunction

I made these spells interact with each other: If you cast a Frost Shard and it hits the Living Flame Projectile, it will enhance the Living Flames to do a frost nova when it explodes.

The problem is that when I enhance the Living Flames with a Frost Shard AND the enhanced Living Flame hits a target, the next Living Flame and Frost Shard Projectiles are always created at the '0' angle, and do not move or create an effect when units are nearby. If I enhance the Living Flame with Frost Shard and the living flame explodes without hitting anything (which I coded to happen after it travelled some distance), the projectiles fire as normal.

I have two theories about why this is happening:
1. Since the projectiles are created at the "null" angle (0 degrees) but not at the "null" coordinates (0,0), the trigger is not registering the angle between the locations in the initial trigger that begins the timer.
2. The timer stops firing.

Any help is appreciated and rep'd
03-20-2008, 10:44 PM#2
Silvenon
I didn't see the whole code, I just looked really quick. There gotta be some interference with those globals, I'm almost positive that they are the cause of the problem (because of MUI).

Btw, mind explaining those globals a bit? (Crap, I'll be in Norway anyways, so I wont be able to reply, and when I return, there will be someone else answering this thread.......nvm, maybe I helped a bit)



P.S. Don't you dare rep me for this :)
03-21-2008, 03:54 AM#3
Castlemaster
Both projectiles are wards, and I encountered problems with enhancing via buffs, so I just changed it to a global boolean. The boolean in question being used for the interfering enhancement mechanic is "udg_LivingFlameFrost". The thing is that, this variable is more like an addendum to the code (it just casts frost nova upon exploding) that is unrelated to the movement of the projectiles. I wrote a comment in the code for the global variables, so just scan the comments

udg_LivingFlameDamageBonus only has to do with the damage factor when the living flame explodes
udg_Elementalist is the caster. It is essentially the Triggering Unit

Is it possible that the "Attach Real()" and "Attach Object()" commands are interfering with each other?
03-21-2008, 02:48 PM#4
Castlemaster
Found the problem:
when the ice shard enhanced the living flame, I neglected to destroy the timer, causing buggy projectiles. Thanks for help though.