HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

HELP with triggering damage over time effects

09-30-2007, 05:23 PM#1
wewso
Hi everyone. I am having problem with triggering DoTs and haven't found any solution yet so I hope you can help me.
I want to have a spell named Corruption that deals damage every 3 seconds for 18 seconds. (Like the one in WOW) I don't want to use any Globals or dummies and just one triggerfor the spell. I have tried these things and none works.
Collapse JASS:
function Trig_Corruption_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A007' ) ) then
        return false
    endif
    return true
endfunction

function Trig_Corruption_Func002C takes nothing returns boolean
    local unit target = GetSpellTargetUnit()
    if ( not ( UnitHasBuffBJ(target, 'B001') == true ) ) then
        return false
    endif
    return true
endfunction

function Trig_Corruption_Actions takes nothing returns nothing
    local unit target = GetSpellTargetUnit()
    if ( Trig_Corruption_Func002C() ) then
        set udg_REAL = GetRandomReal(105.00, 125.00)
        call UnitDamageTargetBJ( GetTriggerUnit(), target, udg_REAL, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_DEATH )
        call CreateTextTagUnitBJ( R2S(udg_REAL), target, 0, 10, 100, 0.00, 100, 0 )
        call SetTextTagVelocityBJ( GetLastCreatedTextTag(), 64, 90 )
        call SetTextTagPermanentBJ( GetLastCreatedTextTag(), false )
        call SetTextTagLifespanBJ( GetLastCreatedTextTag(), 1.50 )
        call SetTextTagFadepointBJ( GetLastCreatedTextTag(), 1.00 )
    else
        call DisplayTextToForce( GetPlayersAll(), "TRIGSTR_138" )
        return
    endif
    call TriggerSleepAction( 3.00 )
    call TriggerExecute( GetTriggeringTrigger() )
endfunction

Code:
Corruption Effect
    Events
        Unit - A unit Starts the effect of an ability
    Conditions
        (Ability being cast) Equal to Corruption 
    Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                ((Triggering unit) has buff Corruption Warlock) Equal to True
            Then - Actions
                Set REAL = (Random real number between 105.00 and 125.00)
                Game - Display to (All players) the text: (String(REAL))
                Unit - Cause Hero[(Player number of (Owner of (Attacking unit)))] to damage (Triggering unit), dealing REAL damage of attack type Magic and damage type Death
                Floating Text - Create floating text that reads (String(REAL)) above (Target unit of ability being cast) with Z offset 0.00, using font size 10.00, color (100.00%, 0.00%, 100.00%), and 0.00% transparency
                Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
                Floating Text - Change (Last created floating text): Disable permanence
                Floating Text - Change the lifespan of (Last created floating text) to 1.50 seconds
                Floating Text - Change the fading age of (Last created floating text) to 1.00 seconds
            Else - Actions
                Skip remaining actions
        Wait 3.00 seconds
        Trigger - Run (This trigger) (ignoring conditions)


Collapse JASS:
function Trig_looooooooop_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A007' ) ) then
        return false
    endif
    return true
endfunction

function Trig_looooooooop_Actions takes nothing returns nothing
    local unit target = GetSpellTargetUnit()
    call UnitDamageTargetBJ( target, GetSpellTargetUnit(), 100.00, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_DEATH )
    call TriggerSleepAction( 2 )
    call UnitDamageTargetBJ( target, GetSpellTargetUnit(), 100.00, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_DEATH )
    call TriggerSleepAction( 2 )
    call UnitDamageTargetBJ( target, GetSpellTargetUnit(), 100.00, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_DEATH )
    call TriggerSleepAction( 2 )
endfunction



The problem appears to be that WE can't detect the Target of ability being cast after waiting seconds. So maybe only jass can help here with some locals, but i dont know jass well so can you please write it for me.

Thank you in advance.
Wewso
09-30-2007, 05:37 PM#2
cohadar
You need to learn to use periodic timers.
Waits don't work ... well they just don't work in 95% of cases.

And start using NewGen.
10-01-2007, 01:19 AM#3
moyack
I could show you how to do that, but... why don't you create your spell with a custom ability based on Shadow Strike?? it has all that you are requiring (even the floating text), and you won't need to trigger anything.
10-01-2007, 03:37 AM#4
sinners_la_b
Just a few tips to give you:
This
Collapse JASS:

function Trig_Corruption_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A007' ) ) then
        return false
    endif
    return true
endfunction


can be replaced with

Collapse JASS:
function Trig_Corruption_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A007'
endfunction

I dont he wants to make the damage the target recieved to be a random real. Your going to want to do something like have a function that damages the unit every three seconds this wil require you to learn to use timers. Then you need an integer that starts at zero and increases by 3 everytime the function is run. Then just use an if statement to check whether the integer is less than 18.
10-01-2007, 06:02 AM#5
Pyrogasm
You might want to check this out: JESP DoT Template
10-01-2007, 04:17 PM#6
wewso
Quote:
Originally Posted by moyack
I could show you how to do that, but... why don't you create your spell with a custom ability based on Shadow Strike?? it has all that you are requiring (even the floating text), and you won't need to trigger anything.


I thaught of creating a spell based on Shadow Strike but the hero Im designing is a Warlock and will have lots of those DoTs (damage over time effects). So I cant base my spells on Shadow Strike because WC3 will mess up the IDs.

Quote:
Originally Posted by Pyrogasm
You might want to check this out: JESP DoT Template


Well i saw this and it looks very good in-game but it doesn't help me because:
1 It doesn't create a buff that when dispelled canceles the effect.
2 The JASS isn't quite editable and i would have problems with adding additional effects. Actualy I can't edit it at all

Quote:
Originally Posted by cohadar
You need to learn to use periodic timers.
Waits don't work ... well they just don't work in 95% of cases.

And start using NewGen.

Timers dont help becase they need globals and i dont want any globals in my spell. Imagine how every player has cast 5 different dots on 4 different targets (2 of which will resist the spell and would want to stop the negative effect) each controled by a different player in a different team which would want to get points for the damage dealt to enemy players. Thats how messed up it is
10-02-2007, 02:47 AM#7
Pyrogasm
You don't need globals for timers. In fact, you usually will "attach" structs or handles to a timer to create a specific instance for that timer. My code can be modified to work based on if a unit has a specific buff or not.

Here's a revised code that does such a thing (changes are in red; I have no way of showing what I removed, only what I added):
Collapse JASS:
//***************************************************************************\\
//                           Spell Name: ExampleDoT                          \\
//                           Spell Author: Pyrogasm                          \\
//                       Conforms to the JESP Standard                       \\
//***************************************************************************\\

constant function ExampleDoT_AbilityId takes nothing returns integer
    return 'A000' //The spell's rawcode.
endfunction

constant function ExampleDoT_DummyUnitId takes nothing returns integer
    return 'h000' //The rawcode of a generic dummy unit.
endfunction

constant function ExampleDoT_BuffId takes integer Level returns integer
    return 'B008'
endfunction

constant function ExampleDoT_Duration takes integer Level returns real
    return 9.00
endfunction

constant function ExampleDoT_TotalDamage takes integer Level returns real
    return 125.00+(8*Level)*(8*Level)
endfunction

constant function ExampleDoT_DamageInterval takes integer Level returns real
    return 2.00-(Level*0.50) //How often the damage occurs.
endfunction

constant function ExampleDoT_EffectPath takes integer Level returns string
    if Level == 1 then
        return "Abilities\\Weapons\\LordofFlameMissile\\LordofFlameMissile.mdl"
    elseif Level == 2 then
        return "Abilities\\Spells\\Demon\\DarkConversion\\ZombifyTarget.mdl"
    elseif Level == 3 then
        return "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl"
    endif

    return "" //Safety return
endfunction

constant function ExampleDoT_EffectAttach takes integer Level returns string
    if Level == 1 then
        return "overhead"
    elseif Level == 2 then
        return "origin"
    elseif Level == 3 then
        return "chest"
    endif

    return "" //Safety return
endfunction

constant function ExampleDoT_ContinueIfDead takes integer Level returns boolean
    return true //If true, the target will still take damage if the caster has died.
endfunction

constant function ExampleDoT_FirstOnCast takes integer Level returns boolean
    return false //If true, the spell will damage the target in the cast function.
endfunction      //The total damage will be the same, however.

//===========================================================================\\
//===========================================================================\\

function ExampleDoT_CastConditions takes nothing returns boolean
    return GetSpellAbilityId() == ExampleDoT_AbilityId()
endfunction

function ExampleDoT_Callback takes nothing returns nothing
    local timer T = GetExpiredTimer()
    local string TTable = GetAttachmentTable(T)
    local integer Level
    local real Duration
    local unit U
    local unit U2 = GetTableUnit(TTable, "ExampleDoT Target")
    local integer BuffId = ExampleDoT_BuffId(Level))

    if (GetUnitAbilityLevel(U2, BuffId > 0) then //No need to see if it's alive; It won't have the buff if it's dead.
        set U = GetTableUnit(TTable, "ExampleDoT Caster")
        set Duration = ExampleDoT_Duration(Level)

        if GetWidgetLife(U) < 0.406 and ExampleDoT_ContinueIfDead(Level) then
            set U = CreateUnit(GetOwningPlayer(U), ExampleDoT_DummyUnitId(), 0.00, 0.00, 0.00)
            call SetTableObject(TTable, "ExampleDoT Caster", U)
            call UnitApplyTimedLife(U, 'BTLF', Duration)

            call UnitDamageTarget(U, U2, ExampleDoT_TotalDamage(Level)*(ExampleDoT_DamageInterval(Level)/Duration), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null)
            call DestroyEffect(AddSpecialEffectTarget(ExampleDoT_EffectPath(Level), U2, ExampleDoT_EffectAttach(Level)))
        elseif GetWidgetLife(U) < 0.406 and not(ExampleDoT_ContinueIfDead(Level)) then
            call UnitRemoveAbility(U2, BuffId)
        else
            call UnitDamageTarget(U, U2, ExampleDoT_TotalDamage(Level)*(ExampleDoT_DamageInterval(Level)/Duration), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null)
            call DestroyEffect(AddSpecialEffectTarget(ExampleDoT_EffectPath(Level), U2, ExampleDoT_EffectAttach(Level)))
        endif

        set U = null
    else
        call PauseTimer(T)
        call CleanAttachedVars(T)
        call DestroyTimer(T)
    endif

    set U2 = null
    set T = null
endfunction

function ExampleDoT_Cast takes nothing returns nothing
    local unit U = GetTriggerUnit()
    local unit U2 = GetSpellTargetUnit()
    local timer T = CreateTimer()
    local string TTable = GetAttachmentTable(T)
    local integer Level = GetUnitAbilityLevel(U, ExampleDoT_AbilityId())
    local real Interval = ExampleDoT_DamageInterval(Level)
    local real Duration = ExampleDoT_Duration(Level)

    if ExampleDoT_FirstOnCast(Level) then
        call UnitDamageTarget(U, U2, ExampleDoT_TotalDamage(Level)*(Interval/Duration), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null)
        call DestroyEffect(AddSpecialEffectTarget(ExampleDoT_EffectPath(Level), U2, ExampleDoT_EffectAttach(Level)))
    endif

    call SetTableObject(TTable, "ExampleDoT Caster", U)
    call SetTableObject(TTable, "ExampleDoT Target", U2)
    call SetTableInt(TTable, "ExampleDoT Level", Level)
    call TimerStart(T, Interval, true, function ExampleDoT_Callback)

    set U = null
    set U2 = null
    set T = null
endfunction

//===========================================================================\\
function InitTrig_ExampleDoT takes nothing returns nothing
    set gg_trg_ExampleDoT = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_ExampleDoT, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_ExampleDoT, Condition(function ExampleDoT_CastConditions))
    call TriggerAddAction(gg_trg_ExampleDoT, function ExampleDoT_Cast)
endfunction